-
Notifications
You must be signed in to change notification settings - Fork 178
/
reptile.carp
181 lines (155 loc) · 5.66 KB
/
reptile.carp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
(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)))