Carp/examples/reptile.carp
Erik Svedäng 889f55fe8f
feat: Remove address (#1223)
* chore: Abuse deftemplate to get rid of Address

* chore: Avoid semicolon at end of define

* fix: address should be useable as an argument to a HOF

* chore: adapt examples to new address signature

* fix: Remove Address from typeOf

* fix: Remove more uses of Address

* fix: Remove more mentions of address in the Haskell code

* fix: Remove test that ensure you can't take the address of non-symbols

* refactor: Moved `address` to Pointer.carp

* refactor: Move address into Pointer module

Co-authored-by: Jorge Acereda <jacereda@gmail.com>
2021-05-27 22:04:46 +02:00

182 lines
5.7 KiB
Plaintext

(use Int)
(use Double)
(use Array)
(load "SDL.carp")
(load "SDL_image.carp")
(load "Vector.carp")
(use Vector2)
(Project.config "title" "Reptile")
(deftype Snake
[body (Array (Vector2 Double))
dir SDL_Keycode
freeze Int])
(use Snake)
(deftype World
[snake Snake
human (Vector2 Double)
dead Bool])
(use World)
(def bg-col 120)
(def grid-size 32)
(defn draw-snake [rend snake]
(let [body-length (length (body snake))]
(for [i 0 body-length]
(let [part (unsafe-nth (body snake) i)
x (* grid-size (to-int @(Vector2.x part)))
y (* grid-size (to-int @(Vector2.y part)))]
(if (= i 0)
(do
(SDL.set-render-draw-color rend 200 255 (+ 100 (* body-length 10)) 255)
(SDL.render-fill-rect rend (Pointer.address &(SDL.rect x y grid-size grid-size))))
(do
(SDL.set-render-draw-color rend 200 (+ 50 (* i (/ 200 body-length))) 100 255)
(SDL.render-fill-rect rend (Pointer.address &(SDL.rect x y grid-size grid-size)))))))))
(defn draw-human [rend human]
(do
(SDL.set-render-draw-color rend 100 100 250 255)
(let [x (* grid-size (to-int @(Vector2.x human)))
y (* grid-size (to-int @(Vector2.y human)))]
(SDL.render-fill-rect rend (Pointer.address &(SDL.rect x y grid-size grid-size))))))
(defn draw [rend world]
(do
(SDL.set-render-draw-blend-mode rend SDL.blend-mode-add)
(SDL.set-render-draw-color rend (- bg-col @(Snake.freeze (World.snake world))) bg-col bg-col 255)
(SDL.render-clear rend)
(draw-snake rend (snake world))
(draw-human rend (World.human world))
(SDL.render-present rend)))
(def input-dir SDL.Keycode.down)
(def reset false)
(defn handle-events [app rend world]
(let [event (SDL.Event.init)]
(while (SDL.Event.poll (Pointer.address &event))
(let [et (SDL.Event.type &event)]
(cond (= et SDL.Event.quit) (SDLApp.stop app)
(= et SDL.Event.key-down) (let [key (SDL.Event.keycode &event)]
(cond
(or (= key SDL.Keycode.right)
(or (= key SDL.Keycode.up)
(or (= key SDL.Keycode.left) (= key SDL.Keycode.down))))
(set! input-dir key)
(= key SDL.Keycode.return) (set! reset true)
(= key SDL.Keycode.escape) (SDLApp.stop app)
()))
())))))
(defn move [vec dir]
(cond
(= SDL.Keycode.right dir) (add &vec &(Vector2.init 1.0 0.0))
(= SDL.Keycode.up dir) (add &vec &(Vector2.init 0.0 -1.0))
(= SDL.Keycode.left dir) (add &vec &(Vector2.init -1.0 0.0))
(= SDL.Keycode.down dir) (add &vec &(Vector2.init 0.0 1.0))
vec))
(defn shift-body [body]
(do
(let [i (- (length body) 2)]
(while (> i -1)
(do
(aset! body (inc i) @(unsafe-nth body i))
(set! i (dec i)))))
@body))
(defn create-human []
(Vector2.init (from-int (random-between 0 26))
(from-int (random-between 0 20))))
(defn kill-human [world]
(let [new-human (create-human)]
(World.set-human world new-human)))
(defn inc2 [i]
(+ i 2))
(defn grow [snake]
(let [new-snake (Snake.update-freeze snake &inc2)
b (Snake.body &new-snake)]
(Snake.set-body new-snake (push-back @b @(unsafe-last b)))))
(defn update-after-kill [world]
(let [s (World.snake &world)
new-s (grow @s)
new-world (kill-human world)]
(World.set-snake new-world new-s)))
(defn check-for-kill [world]
(let [s (World.snake world)
h (World.human world)
b (Snake.body s)
head (unsafe-first b)]
(if (= head h)
(update-after-kill @world)
@world)))
(defn check-world [world]
(let [snake (World.snake world)
b (Snake.body snake)
head (unsafe-first b)
x @(Vector2.x head)
y @(Vector2.y head)]
(World.set-dead @world (or (< x 0.0)
(or (> x 26.0)
(or (< y 0.0) (> y 24.0)))))))
(defn tick [world]
(let [s (Snake.set-dir @(World.snake world) input-dir)
b (Snake.body &s)
new-head (move @(unsafe-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)
world-checked (check-world &world-after-snake-move)]
(check-for-kill &world-checked)))
(defn create-world []
(World.init (Snake.init [(Vector2.init 10.0 10.0)
(Vector2.init 9.0 10.0)
(Vector2.init 8.0 10.0)
(Vector2.init 7.0 10.0)]
SDL.Keycode.down
0)
(create-human)
false))
(defn render-dead [rend]
(do
(SDL.set-render-draw-blend-mode rend SDL.blend-mode-add)
(SDL.set-render-draw-color rend 200 90 90 255)
(SDL.render-clear rend)
(SDL.render-present rend)
(SDL.delay 2000)))
(defn main []
(let-do [app (SDLApp.create "R E P T I L E" 832 640)
rend @(SDLApp.renderer &app)
world (create-world)]
(while (not @(World.dead &world))
(if reset
(do
(set! input-dir SDL.Keycode.right)
(set! world (create-world))
(set! reset false))
(do
(let [new-world (tick &world)]
(set! world new-world))
(handle-events &app rend &world)
(draw rend &world)
(SDL.delay 50))))
(render-dead rend)))