Carp/examples/reptile.carp
2017-09-06 10:05:19 +02:00

235 lines
6.8 KiB
Plaintext

(use IO)
(use System)
(use Int)
(use Double)
(use Array)
(load "core/sdl.carp")
(load "core/sdl_image.carp")
(use Keycode)
(add-cflag "-fsanitize=address")
(deftype Vec2
[x Int
y Int])
(use Vec2)
(def RIGHT 0)
(def UP 1)
(def LEFT 2)
(def DOWN 3)
(deftype Snake
[body (Array Vec2)
dir Int
freeze Int
])
(use Snake)
(deftype Human
[pos Vec2])
(use Human)
(deftype World
[snake Snake
humans (Array Human)])
(use World)
(def bg-col 120)
(def grid-size 32)
(defn draw-snake [rend snake]
(let [body-count (count (body snake))]
(for [i 0 body-count]
(let [part (nth (body snake) i)
x (* grid-size (Vec2.x &part))
y (* grid-size (Vec2.y &part))]
(do
;; (if (= i 0)
;; (do
;; (SDL_SetRenderDrawColor rend 200 255 100 255)
;; (SDL_RenderFillRect rend (address (make-rect x y grid-size grid-size))))
;; ())
(SDL_SetRenderDrawColor rend 200 (+ 50 (* i (/ 200 body-count))) 100 255)
(SDL_RenderFillRect rend (address (make-rect x y grid-size grid-size))))))))
(defn draw-human [rend human]
(do
(SDL_SetRenderDrawColor rend 100 100 250 255)
(let [x (* grid-size (Vec2.x (pos &human)))
y (* grid-size (Vec2.y (pos &human)))]
(SDL_RenderFillRect rend (address (make-rect x y grid-size grid-size))))))
(defn draw [rend world]
(do
(SDL_SetRenderDrawBlendMode rend SDL_BLENDMODE_ADD)
(SDL_SetRenderDrawColor rend (- bg-col (* 2 (Snake.freeze (World.snake world)))) bg-col bg-col 255)
(SDL_RenderClear rend)
(draw-snake rend (snake world))
;; (let [hums (World.humans &world)]
;; (for [i 0 (count hums)]
;; (draw-human rend (nth hums i))))
(SDL_RenderPresent rend)
))
(def input-dir 1)
(def reset false)
(defn handle-events [app rend world]
(let [event (SDL_Event_init)]
(while (SDL_PollEvent (address event))
(let [et (event-type &event)]
(cond (= et SDL_QUIT) (quit app)
(= et SDL_KEYDOWN) (let [key (event-keycode &event)]
(cond
(= key SDLK_RIGHT) (set! input-dir RIGHT)
(= key SDLK_UP) (set! input-dir UP)
(= key SDLK_LEFT) (set! input-dir LEFT)
(= key SDLK_DOWN) (set! input-dir DOWN)
(= key SDLK_RETURN) (set! reset true)
(= key SDLK_ESCAPE) (quit app)
(println &"Unrecognized key.")))
()
;;(println "Some other event happened...")
)))))
(defn add-vec [a b]
(Vec2.init (+ (x &a) (x &b))
(+ (y &a) (y &b))))
(defn eq-vec [a b]
(and (= (x a) (x b))
(= (y a) (y b))))
(defn move [vec dir]
(cond
(= RIGHT dir) (add-vec vec (Vec2.init 1 0))
(= UP dir) (add-vec vec (Vec2.init 0 (- 0 1)))
(= LEFT dir) (add-vec vec (Vec2.init (- 0 1) 0))
(= DOWN dir) (add-vec vec (Vec2.init 0 1))
vec))
;; Replace this with Array.shift
(defn shift-body [body]
(do
;; (let [i (- (Array.count &body) 2)]
;; (while (> i (- 0 1))
;; (do
;; (aset! body (inc i) (copy (nth body i)))
;; (set! i (dec i)))))
body))
(defn create-human []
(Human.init (Vec2.init (random-between 8 26)
(random-between 4 20))))
;; (defn kill-human [world index]
;; (let [humans (World.humans world)
;; new-human (create-human)
;; humans2 (aset humans index new-human)]
;; (World.set-humans world humans2)))
(defn last [xs]
(Array.nth xs (dec (Array.count &xs))))
(defn grow [snake]
(let [new-snake (Snake.set-freeze snake 5)
b (Snake.body new-snake)]
(Snake.set-body new-snake (push-back b (last b)))))
(defn check-for-kill [world]
(let [s (World.snake world)
b (Snake.body s)
head (nth b 0)
humans (World.humans world)]
world
;; (do
;; (for [i 0 (count humans)]
;; (if (eq-vec head (pos (nth humans i)))
;; (do
;; ;;(set! world (World.set-snake world (grow s)))
;; (set! world (kill-human world i)))
;; ()))
;; world)
))
(defn shorten-snake [snake]
(Snake.set-body snake (Array.pop-back (Snake.body snake))))
;; (defn tick [w1]
;; (let [s1 (World.snake w1)
;; s5 (if (< (Snake.freeze s1) 1)
;; (let [s2 (if (or (= (Snake.dir s1) input-dir)
;; (= 1 (count (Snake.body s1))))
;; s1
;; (let [s1b (Snake.set-dir s1 input-dir)
;; s1c (shorten-snake s1b)]
;; s1c))
;; b1 (Snake.body s2)
;; head (nth b1 0)
;; new-head (move head (dir s2))
;; b2 (shift-body b1)
;; b3 (aset b2 0 new-head)
;; s3 (Snake.set-body s2 b3)]
;; s3)
;; (let [s2 (Snake.set-dir s1 input-dir)
;; s3 (Snake.set-freeze s2 (- (Snake.freeze s1) 1))]
;; s3))
;; w2 (World.set-snake w1 s5)]
;; (check-for-kill w2)))
(defn maybe-shorten [snake]
(if (or (= (Snake.dir snake) input-dir)
(= 1 (count (Snake.body snake))))
snake
snake))
;; (do
;; (println "Shorten!")
;; (shorten-snake snake))
(defn tick [world]
(let [s (Snake.set-dir (maybe-shorten (World.snake world)) input-dir)
b (Snake.body s)
new-head (move (nth b 0) (dir s))
new-body (aset (shift-body b) 0 new-head)
new-snake (Snake.set-body s new-body)
world-after-snake-move (World.set-snake world new-snake)]
(check-for-kill world-after-snake-move)))
(defn create-world []
(World.init (Snake.init [(Vec2.init 10 10)
(Vec2.init 9 10)
(Vec2.init 8 10)
(Vec2.init 7 10)
(Vec2.init 6 10)
(Vec2.init 5 10)
(Vec2.init 4 10)
(Vec2.init 3 10)
(Vec2.init 2 10)]
DOWN
0)
(repeat 30 create-human)))
(defn main []
(let [app (app-init &"R E P T I L E" 1024 768)
rend (app-renderer app)
world (create-world)]
(while true
(do
(if reset
(do
(set! input-dir RIGHT)
(set! world (create-world))
(set! reset false))
())
(let [new-world (tick world)]
(set! world new-world))
(handle-events app rend world)
(draw rend world)
(SDL_Delay 50)))))