Skip to content

Commit e1c6792

Browse files
committed
Big Changes
The entire game was almost completely rewritten. Added fast traces, missile's fragments and more. Unfortunately, the tests became incorrect, so I deleted them. I'm going to write new tests as soon as I can.
1 parent 79ec2e1 commit e1c6792

13 files changed

Lines changed: 487 additions & 690 deletions

File tree

src/hyperspace/game.clj

Lines changed: 129 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,129 @@
1-
(ns hyperspace.game
2-
(:use (hyperspace geometry
3-
gravity
4-
world)))
5-
6-
(defn get-player
7-
[world name]
8-
(first (filter #(= name (:name %)) (:players world))))
9-
10-
(defn update-player-params
11-
[world name heading power]
12-
(assoc world
13-
:players (map (fn [player]
14-
(if (= (:name player) name)
15-
(assoc player
16-
:heading heading
17-
:power power)
18-
player))
19-
(:players world))))
20-
21-
(defn fire
22-
[world player-name]
23-
(let [player (get-player world player-name)
24-
{point :center
25-
power :power
26-
angle :heading} player
27-
bullet (make-bullet point (make-vector-radial power angle))]
28-
(assoc world
29-
:bullets (conj (:bullets world) bullet))))
30-
31-
(defn destroy-bullet?
32-
[bullet planets]
33-
(let [bullet-center (:center bullet)]
34-
(some (fn [{planet-radius :radius
35-
planet-center :center}]
36-
(<= (point-distance bullet-center
37-
planet-center)
38-
planet-radius))
39-
planets)))
40-
41-
(defn update-bullet
42-
[bullet planets]
43-
(if (= (:status bullet) :dead)
44-
bullet
45-
(let [acceleration (get-acceleration bullet planets)
46-
{position :center
47-
velocity :velocity
48-
traces :traces} bullet]
49-
(assoc bullet
50-
:center (move-point position velocity)
51-
:velocity (vector-sum velocity acceleration)
52-
:status (if (destroy-bullet? bullet planets) :dead :alive)
53-
:traces (conj traces position)))))
54-
55-
(defn update-world
56-
"Simulates few steps for world. Returns new world and remaining time."
57-
[world time]
58-
(let [{bullets :bullets
59-
planets :planets} world]
60-
(if (< time 1)
61-
[world time]
62-
(recur (assoc world
63-
:bullets (doall (map #(update-bullet % planets) bullets)))
64-
(- time 1)))))
1+
(ns hyperspace.game
2+
(:use [hyperspace world geometry gravity misc]))
3+
4+
(defn turn-right
5+
[{[player & _] :players
6+
:as world}
7+
delta-angle]
8+
(let [{[angle, _] :heading} player]
9+
(assoc-in world
10+
[:players 0 :heading 0]
11+
(- angle delta-angle))))
12+
13+
(defn turn-left
14+
[{[player & _] :players
15+
:as world}
16+
delta-angle]
17+
(let [{[angle, _] :heading} player]
18+
(assoc-in world
19+
[:players 0 :heading 0]
20+
(+ angle delta-angle))))
21+
22+
(defn increase-power
23+
[world delta-power]
24+
(let [power (get-in world [:players 0 :heading 1])]
25+
(assoc-in world
26+
[:players 0 :heading 1]
27+
(saturation (+ power delta-power)
28+
1 10))))
29+
30+
(defn decrease-power
31+
[world delta-power]
32+
(let [power (get-in world [:players 0 :heading 1])]
33+
(assoc-in world
34+
[:players 0 :heading 1]
35+
(saturation (- power delta-power)
36+
1 10))))
37+
38+
(defn fire
39+
[{[player & _] :players
40+
:as world}]
41+
(let [{position :position
42+
[_, power :as heading] :heading} player
43+
missile-position (-> (polar->cartesian heading)
44+
normilize-vector
45+
(multiply-by-scalar (+ player-radius
46+
missile-radius))
47+
(vector-sum position))
48+
missile-velocity (-> (polar->cartesian heading)
49+
normilize-vector
50+
(multiply-by-scalar (* power 100)))]
51+
(add-missile world
52+
missile-position
53+
missile-velocity)))
54+
55+
(defn update-particle
56+
[{position :position
57+
velocity :velocity
58+
:as particle}
59+
planets
60+
delta-time]
61+
(let [acceleration (apply vector-sum
62+
(map #(gravity-acceleration particle %)
63+
planets))
64+
;; FIXME: Duplicate code
65+
new-velocity (-> acceleration
66+
(multiply-by-scalar (* delta-time 1e-3))
67+
(vector-sum velocity))
68+
new-position (-> new-velocity
69+
(multiply-by-scalar (* delta-time 1e-3))
70+
(vector-sum position))]
71+
(assoc particle
72+
:position new-position
73+
:velocity new-velocity)))
74+
75+
(defn update-traces
76+
[traces
77+
{position :position
78+
trace-index :trace-index}]
79+
(update-in traces [trace-index] conj position))
80+
81+
(defn break-particle
82+
[{particle-position :position
83+
particle-radius :radius
84+
velocity :velocity
85+
radius :radius
86+
:as particle}
87+
planets]
88+
(let [planet (some #(when (circle-X-circle? % particle) %) planets)]
89+
(if (and planet (> radius 1.0))
90+
(let [{planet-position :position
91+
planet-radius :radius} planet
92+
93+
fragments-position (-> (vector-subtract particle-position planet-position)
94+
normilize-vector
95+
(multiply-by-scalar (+ particle-radius planet-radius 5))
96+
(vector-sum planet-position))]
97+
(repeatedly 5
98+
(fn []
99+
(make-fragment fragments-position
100+
(polar->cartesian [(rand (* 2 Math/PI)),
101+
(/ (vector-length velocity) 2)])
102+
(- radius 2)))))
103+
())))
104+
105+
(defn update-world
106+
[{missiles :missiles
107+
planets :planets
108+
fragments :fragments
109+
traces :traces
110+
:as world}
111+
delta-time]
112+
(let [broken-particles (mapcat #(break-particle % planets)
113+
(concat missiles fragments))
114+
;; FIXME: Duplicate code
115+
new-missiles (->> missiles
116+
(filter #(circle-X-rectangle? % world))
117+
(remove #(circle-X-any-circle? % planets))
118+
(map #(update-particle % planets delta-time)))
119+
new-fragments (->> fragments
120+
(concat broken-particles)
121+
(filter #(circle-X-rectangle? % world))
122+
(remove #(circle-X-any-circle? % planets))
123+
(map #(update-particle % planets delta-time)))
124+
125+
new-traces (reduce update-traces traces new-missiles)]
126+
(assoc world
127+
:missiles new-missiles
128+
:fragments new-fragments
129+
:traces new-traces)))

src/hyperspace/geometry.clj

Lines changed: 65 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,65 @@
1-
(ns hyperspace.geometry)
2-
3-
(defrecord Point2 [x y])
4-
(defrecord Vector2 [x y])
5-
6-
(def make-point ->Point2)
7-
(def make-vector ->Vector2)
8-
9-
(defn make-vector-radial
10-
[length angle]
11-
(let [x (* length (Math/cos angle))
12-
y (* length (Math/sin angle))]
13-
(make-vector x y)))
14-
15-
(defn move-point
16-
[point vector]
17-
(let [new-x (+ (:x point) (:x vector))
18-
new-y (+ (:y point) (:y vector))]
19-
(make-point new-x new-y)))
20-
21-
(defn point-distance
22-
[p1 p2]
23-
(let [x1 (:x p1)
24-
x2 (:x p2)
25-
y1 (:y p1)
26-
y2 (:y p2)]
27-
(Math/sqrt (+ (Math/pow (- x2 x1) 2)
28-
(Math/pow (- y2 y1) 2)))))
29-
30-
(defn vector-sum
31-
[v1 v2]
32-
(let [new-x (+ (:x v1) (:x v2))
33-
new-y (+ (:y v1) (:y v2))]
34-
(make-vector new-x new-y)))
35-
36-
(defn vector-length
37-
[v]
38-
(Math/sqrt (+ (Math/pow (:x v) 2)
39-
(Math/pow (:y v) 2))))
40-
41-
(defn vector-bearing
42-
[v]
43-
(Math/atan2 (:y v) (:x v)))
44-
45-
(defn bearing-to
46-
[p1 p2]
47-
(let [x1 (:x p1)
48-
x2 (:x p2)
49-
y1 (:y p1)
50-
y2 (:y p2)]
51-
(Math/atan2 (- y2 y1) (- x2 x1))))
1+
(ns hyperspace.geometry)
2+
3+
(def
4+
^{:arglists '([vtr & vtrs])
5+
:doc "Returns the sum of vectors. The result vector has a minimum
6+
possible dimension."}
7+
vector-sum (partial mapv +))
8+
9+
(def
10+
^{:arglists '([vtr & vtrs])
11+
:doc "If no vtrs are supplied, returns the negation of vtr, else
12+
subtracts the vtrs from vtr and returns the result. The result
13+
vector has a minimum possible dimension."}
14+
vector-subtract
15+
(partial mapv -))
16+
17+
(defn multiply-by-scalar
18+
"Returns the multiplication of vtr and scalar."
19+
[vtr scalar]
20+
(mapv #(* scalar %) vtr))
21+
22+
(defn vector-length
23+
"Returns the length of vtr."
24+
[vtr]
25+
(Math/sqrt (reduce #(+ %1 (* %2 %2)) 0.0 vtr)))
26+
27+
(defn normilize-vector
28+
[vtr]
29+
(let [length (vector-length vtr)]
30+
(mapv #(/ % length) vtr)))
31+
32+
(defn distance
33+
"Returns the distance between p1 and p2."
34+
[p1 p2]
35+
(vector-length (vector-subtract p1 p2)))
36+
37+
(defn polar->cartesian
38+
"Converts polar coordinates to the cartesian ones."
39+
[[a, d]]
40+
[(* d (Math/cos a))
41+
(* d (Math/sin a))])
42+
43+
(defn cartesian->polar
44+
"Converts cartesian cooradinates to the polar ones."
45+
[[x, y]]
46+
[(Math/atan2 y x)
47+
(Math/sqrt (+ (* x x) (* y y)))])
48+
49+
(defn circle-X-circle?
50+
"Does the first circle intersects the second one?"
51+
[{position1 :position radius1 :radius}
52+
{position2 :position radius2 :radius}]
53+
(<= (distance position1 position2)
54+
(+ radius1 radius2)))
55+
56+
(defn circle-X-any-circle?
57+
[circle other-circles]
58+
(some #(circle-X-circle? % circle) other-circles))
59+
60+
(defn circle-X-rectangle?
61+
"Does the circle intersects the rectangle?"
62+
[{[cx, cy] :position radius :radius}
63+
{[rx, ry] :position [width, height] :size}]
64+
(and (<= (- rx radius) cx (+ rx width radius))
65+
(<= (- ry radius) cy (+ ry height radius))))

src/hyperspace/gravity.clj

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
1-
(ns hyperspace.gravity
2-
(:use (hyperspace geometry)))
3-
4-
(def gravity-constant 6.6725e-11)
5-
(def bullet-mass 1)
6-
7-
(defn gravity-force
8-
[m1 m2 distance]
9-
(/ (* gravity-constant m1 m2) (Math/pow distance 2)))
10-
11-
(defn planet-gravity-force
12-
[planet bullet]
13-
(let [planet-center (:center planet)
14-
bullet-center (:center bullet)
15-
planet-mass (:mass planet)
16-
distance (point-distance planet-center bullet-center)
17-
force (gravity-force planet-mass bullet-mass distance)
18-
acceleration (/ force bullet-mass)
19-
angle (bearing-to bullet-center planet-center)]
20-
(make-vector-radial acceleration angle)))
21-
22-
(defn get-acceleration
23-
[bullet planets]
24-
(reduce #(vector-sum %1 (planet-gravity-force %2 bullet))
25-
(make-vector 0 0)
26-
planets))
1+
(ns hyperspace.gravity
2+
(:use [hyperspace geometry]))
3+
4+
(def gravity-constant 0.1;6.6725e-11
5+
)
6+
7+
(defn gravity-acceleration
8+
[{position1 :position mass1 :mass}
9+
{position2 :position mass2 :mass}]
10+
(let [d (distance position1 position2)
11+
force (/ (* gravity-constant mass1 mass2)
12+
(* d d))
13+
acceleration (/ force mass1)]
14+
(-> (vector-subtract position2 position1)
15+
normilize-vector
16+
(multiply-by-scalar acceleration))))

src/hyperspace/main.clj

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
(ns hyperspace.main
2-
(:use (hyperspace ui
3-
world)))
4-
5-
(defn -main
6-
[& args]
7-
(let [world (generate-world)]
8-
(start-ui world)))
1+
(ns hyperspace.main
2+
(:use [hyperspace game geometry ui world]
3+
[clojure.pprint :only (pprint)]))
4+
5+
(defn -main
6+
[& args]
7+
(start-ui (generate-world 800 600)))

src/hyperspace/misc.clj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@
44
"Returns a random integer between low (inclusive) and high (inclusive)"
55
[low high]
66
(+ low (rand-int (+ 1 (- high low)))))
7+
8+
(defn saturation
9+
[value low high]
10+
(cond
11+
(< value low) low
12+
(< high value) high
13+
:else value))

0 commit comments

Comments
 (0)