├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .yarn
└── releases
│ └── yarn-classic.cjs
├── .yarnrc.yml
├── README.md
├── assets
├── bsconfig.json
├── index.html
├── package.json
├── public
├── assets
│ ├── car_1.png
│ ├── car_2.png
│ ├── car_3.png
│ ├── car_4.png
│ ├── car_5.png
│ ├── post.png
│ ├── roadsign.png
│ ├── roadsign_left.png
│ ├── stone.png
│ └── tree.png
└── index.html
├── src
├── Car.res
├── Common.res
├── Control.res
├── Index.res
├── IndexHot.res
├── Object.res
├── Road.res
├── Score.res
├── Screen.res
├── Timer.res
└── Track.res
└── yarn.lock
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: ["master"]
6 | pull_request:
7 | branches: ["master"]
8 |
9 | jobs:
10 | build:
11 | name: Test
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v3
15 |
16 | - name: Set Node.js 20.x
17 | uses: actions/setup-node@v3
18 | with:
19 | node-version: 20.x
20 |
21 | - name: Run install
22 | uses: borales/actions-yarn@v4
23 | with:
24 | cmd: install --frozen-lockfile
25 | env:
26 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # if needed
27 | - name: Build
28 | uses: borales/actions-yarn@v4
29 | with:
30 | cmd: build # will run `yarn build`
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | lib
3 | node_modules
4 | .yarn/install-state.gz
5 | .merlin
6 | .vscode
7 | .bsb.lock
8 | .DS_Store
9 | .cache
10 | *.bs.js
11 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | yarnPath: .yarn/releases/yarn-classic.cjs
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ReTurbo
2 |
3 | 
4 |
5 | Some fun with [Reprocessing](https://github.com/schmavery/reprocessing) and [BsbNative](https://github.com/bsansouci/bsb-native)
6 |
7 | ## How To
8 |
9 | ### Install
10 |
11 | `yarn`
12 |
13 | ### Build
14 |
15 | `yarn build` and `yarn vite:build`
16 |
17 | ### Start
18 |
19 | There are a few ways to try this out:
20 |
21 | After building you could run a static server, like `python -m SimpleHTTPServer` and go to `localhost:8000`. Or you're using safari you can simply open the `index.html` and tick `Develop > Disable Cross-Origin Restrictions`.
22 |
23 | Alternatively using Vite: `yarn preview` will host the game at `localhost:4173`
24 |
25 | ### Controls
26 |
27 | Use the arrow keys to turn and brake, whilst space restarts the game. Alternatively, click/touch
28 | the edges to turn and the timer to restart.
29 |
30 | ## Fun Stuff I used or forked
31 |
32 | - [ReScript](https://rescript-lang.org)
33 | - [Reprocessing](https://github.com/schmavery/reprocessing)
34 | - [ReasonGl](https://github.com/bsansouci/reasongl-web)
35 | - [Vite](https://vitejs.dev)
36 |
--------------------------------------------------------------------------------
/assets:
--------------------------------------------------------------------------------
1 | public/assets
--------------------------------------------------------------------------------
/bsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "re-turbo",
3 | "sources": "src",
4 | "bs-dependencies": ["reprocessing"],
5 | "entries": [{
6 | "backend": "js",
7 | "main-module": "Index"
8 | }],
9 | "package-specs": {
10 | "module": "es6"
11 | },
12 | "refmt": 3
13 | }
14 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ReTurbo
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "re-turbo",
3 | "scripts": {
4 | "build": "rescript build -with-deps",
5 | "clean": "rescript clean && rimraf dist/",
6 | "refmt": "rescript format src/*",
7 | "dev": "vite",
8 | "vite:build": "vite build",
9 | "preview": "vite preview",
10 | "format": "prettier --write \"src/**/*.ts\""
11 | },
12 | "dependencies": {
13 | "reprocessing": "github:RawToast/reprocessing#ml"
14 | },
15 | "devDependencies": {
16 | "rescript": "^10.1.3",
17 | "rimraf": "^3.0.0",
18 | "vite": "^5.1.6"
19 | },
20 | "packageManager": "yarn@4.1.1",
21 | "version": "0.0.0"
22 | }
23 |
--------------------------------------------------------------------------------
/public/assets/car_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/car_1.png
--------------------------------------------------------------------------------
/public/assets/car_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/car_2.png
--------------------------------------------------------------------------------
/public/assets/car_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/car_3.png
--------------------------------------------------------------------------------
/public/assets/car_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/car_4.png
--------------------------------------------------------------------------------
/public/assets/car_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/car_5.png
--------------------------------------------------------------------------------
/public/assets/post.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/post.png
--------------------------------------------------------------------------------
/public/assets/roadsign.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/roadsign.png
--------------------------------------------------------------------------------
/public/assets/roadsign_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/roadsign_left.png
--------------------------------------------------------------------------------
/public/assets/stone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/stone.png
--------------------------------------------------------------------------------
/public/assets/tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RawToast/ReTurbo/20d1199e20e5c0c0337fa499b7e2f3d9ce8ee073/public/assets/tree.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ReTurbo
6 |
27 |
28 |
29 |
30 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/Car.res:
--------------------------------------------------------------------------------
1 | type state = {
2 | speed: float,
3 | positionBonus: float,
4 | velocity: float,
5 | // slide: option(float),
6 | offset: float,
7 | }
8 |
9 | let carWidth = 110
10 | let carHeight = 55
11 |
12 | module Display = {
13 | type asset =
14 | | Straight
15 | | LeftTurn
16 | | HeavyLeftTurn
17 | | RightTurn
18 | | HeavyRightTurn
19 |
20 | type t = {
21 | offset: float,
22 | width: float,
23 | height: float,
24 | asset: asset,
25 | z: float,
26 | }
27 |
28 | let make = car => {
29 | let asset = switch car.velocity {
30 | | _ if car.velocity == 0. => Straight
31 | | _ if car.velocity > 12. => HeavyRightTurn
32 | | _ if car.velocity > 0.2 => RightTurn
33 | | _ if car.velocity < -12. => HeavyLeftTurn
34 | | _ if car.velocity < 0.2 => LeftTurn
35 | | _ => Straight
36 | }
37 |
38 | {
39 | offset: car.offset,
40 | asset: asset,
41 | width: float_of_int(carWidth),
42 | height: float_of_int(carHeight),
43 | z: 1.,
44 | }
45 | }
46 | }
47 |
48 | let vLowSpeed = 90.
49 | let lowSpeed = 110.
50 | let midSpeed = 160.
51 | let highSpeed = 220.
52 | let vHighSpeed = 260.
53 |
54 | let grassMaxSpeed = 100.
55 |
56 | let maxSpeed = 250.
57 | /* 60-0 in 3 seconds */
58 | let brakeFactor = 60. *. 1.6 /. (Common.frameRate *. 3.)
59 |
60 | let speedInMph = state => state.speed /. 1.6 |> int_of_float |> string_of_int
61 |
62 | let updateOffset = (state, force) => {
63 | let offset = state.offset -. force
64 | let offset = max(offset, Common.minOffset)
65 | let offset = min(offset, Common.maxOffset)
66 |
67 | {...state, offset: offset}
68 | }
69 |
70 | let turn = (key: Control.turn, state: state) => {
71 | let updateOffsetUsingForce = s => updateOffset(s, s.velocity /. 700.)
72 | let highSpeed = state.speed > 176. && state.speed < 200.
73 | let vHighSpeed = state.speed > 200.
74 | let updateVelocity = amount => {
75 | let velocity = state.velocity +. amount
76 | {
77 | ...state,
78 | velocity: velocity >= -0.5 && velocity <= 0.5 ? 0. : velocity,
79 | }}
80 | switch key {
81 | | LEFT if state.velocity > -12. && vHighSpeed => updateVelocity(-0.8)
82 | | LEFT if state.velocity > -13. && highSpeed => updateVelocity(-0.9)
83 | | LEFT if state.velocity > -14. => updateVelocity(-1.)
84 | | P_LEFT if state.velocity > -18. && vHighSpeed => updateVelocity(-2.)
85 | | P_LEFT if state.velocity > -16. => updateVelocity(-3.5)
86 | | RIGHT if state.velocity < 12. && vHighSpeed => updateVelocity(0.8)
87 | | RIGHT if state.velocity < 13. && highSpeed => updateVelocity(0.9)
88 | | RIGHT if state.velocity < 14. => updateVelocity(1.)
89 | | P_RIGHT if state.velocity < 18. && vHighSpeed => updateVelocity(2.)
90 | | P_RIGHT if state.velocity < 16. => updateVelocity(3.5)
91 | | _ if state.velocity > 0. => updateVelocity(-1.)
92 | | _ if state.velocity < 0. => updateVelocity(1.)
93 | | _ => state
94 | } |> updateOffsetUsingForce
95 | }
96 |
97 | let progression = state =>
98 | 0. >= state.speed ? 0. : state.speed *. (1. +. state.positionBonus /. 100.) /. 25.
99 |
100 | let roadEffect = (direction, incline, state) => {
101 | /* Current max velocity is 6, curves are from 0.08 to 0.6 */
102 | let offTrack = state => {
103 | let carCentre = float_of_int(carWidth) /. 2.1
104 | let offset = state.offset
105 |
106 | let offRoadAdjustment = state => {
107 | let isOffLeft = (offset > 0. && offset > 1.) || (offset < 0. && offset < -1.)
108 | let isOffRight =
109 | (offset < 0. && offset < -1. +. carCentre) || (offset > 0. && offset > 1. +. carCentre)
110 |
111 | let offRoadFactor = switch (isOffLeft, isOffRight) {
112 | | (true, true) => 1.
113 | | (false, false) => 0.3
114 | | _ => 0.
115 | }
116 | let isOff = isOffRight || isOffLeft
117 | let update = state =>
118 | state.speed > grassMaxSpeed
119 | ? {...state, speed: state.speed -. offRoadFactor *. 0.8}
120 | : {...state, speed: state.speed -. offRoadFactor *. 0.1}
121 |
122 | isOff ? update(state) : state
123 | }
124 | state |> offRoadAdjustment
125 | }
126 |
127 | let apexBonus = state => {
128 | let offset = state.offset
129 | let initBonus = switch direction {
130 | | Track.Right(t) => (0. -. t) *. offset /. 22.
131 | | Track.Left(t) => t *. offset /. 22.
132 | | _ => 0.
133 | }
134 |
135 | let positionBonus = switch initBonus {
136 | | _ if initBonus > 5. => 5.
137 | | _ if initBonus < -5. => -5.
138 | | 0. => 0.
139 | | _ => initBonus
140 | }
141 |
142 | {...state, positionBonus: positionBonus}
143 | }
144 |
145 | let cornerEffect = state =>
146 | switch direction {
147 | | Track.Left(force) => force *. 0.1 *. state.speed /. 350. |> updateOffset(state)
148 | | Track.Right(force) => force *. -0.1 *. state.speed /. 350. |> updateOffset(state)
149 | | _ => state
150 | }
151 |
152 | let hillEffect = state => {
153 | let incline = incline > 0. ? incline *. 0.5 : incline
154 | let effect = incline *. 0.02
155 |
156 | effect != 0. ? {...state, speed: state.speed -. effect} : state
157 | }
158 |
159 | state |> cornerEffect |> offTrack |> apexBonus |> hillEffect
160 | }
161 |
162 | let accelerate = (isBrake, state) => {
163 | let accel = switch state.speed {
164 | | _ if maxSpeed == state.speed => maxSpeed
165 | | _ if vLowSpeed > state.speed => log((highSpeed -. state.speed) /. 4.) /. 8.
166 | | _ if lowSpeed > state.speed => log((highSpeed -. state.speed) /. 8.) /. 12.
167 | | _ if midSpeed > state.speed => log((vHighSpeed -. state.speed) /. 10.) /. 20.
168 | | _ if highSpeed > state.speed => log((maxSpeed -. state.speed) /. 12.) /. 22.
169 | | _ if vHighSpeed > state.speed => log((maxSpeed -. state.speed) /. 14.) /. 25.
170 | | _ => log((maxSpeed -. state.speed) /. 16.) /. 25.
171 | }
172 |
173 | let speed = isBrake ? max(0., state.speed -. brakeFactor) : state.speed +. accel
174 | let speed = max(0., speed)
175 | let speed = min(maxSpeed, speed)
176 |
177 | {...state, speed: speed}
178 | }
179 |
180 | let init = {
181 | velocity: 0.,
182 | offset: 0.,
183 | speed: 0.,
184 | positionBonus: 0.,
185 | }
186 |
--------------------------------------------------------------------------------
/src/Common.res:
--------------------------------------------------------------------------------
1 | let height = 320
2 | let width = 568
3 | let heightF = float_of_int(height)
4 | let widthF = float_of_int(width)
5 | let centrePoint = widthF /. 2.
6 | let centreHeight = heightF /. 2.
7 | let horizon = heightF /. 3. *. 2.
8 |
9 | let minOffset = -2.
10 | let maxOffset = 2.
11 | let roadWidth = 600.
12 | let frameRate = 60.
13 |
14 | let planes = 100
15 |
16 | let cameraDepth = 1. /. tan(80. /. 2. *. 3.1459)
17 |
--------------------------------------------------------------------------------
/src/Control.res:
--------------------------------------------------------------------------------
1 | type state = {
2 | right: bool,
3 | left: bool,
4 | brake: bool,
5 | reset: bool,
6 | }
7 |
8 | type turn =
9 | | LEFT
10 | | P_LEFT
11 | | RIGHT
12 | | P_RIGHT
13 | | NONE
14 |
15 | let init = {right: false, left: false, brake: false, reset: false}
16 | let isLeft = state => state.left && !state.right
17 | let isRight = state => state.right && !state.left
18 | let isBrake = state => state.brake
19 | let isReset = state => state.reset
20 |
21 | let getTurn = state =>
22 | switch (isRight(state), isLeft(state), isBrake(state)) {
23 | | (true, false, false) => RIGHT
24 | | (true, false, true) => P_RIGHT
25 | | (false, true, false) => LEFT
26 | | (false, true, true) => P_LEFT
27 | | _ => NONE
28 | }
29 |
30 | open Reprocessing_Events
31 | let keyDown = (code, state) =>
32 | switch code {
33 | | Left => {...state, left: true}
34 | | Right => {...state, right: true}
35 | | Down => {...state, brake: true}
36 | | Up => {...state, reset: true}
37 | | _ => state
38 | }
39 |
40 | let keyUp = (code, state) =>
41 | switch code {
42 | | Left => {...state, left: false}
43 | | Right => {...state, right: false}
44 | | Down => {...state, brake: false}
45 | | Up => {...state, reset: false}
46 | | _ => state
47 | }
48 |
49 | let breakY = 350
50 | let isMHardLeft = (x, y) => 250 > x && y > breakY
51 | let isMHardRight = (x, y) => x > 525 && y > breakY
52 | let isMLeft = x => 250 > x
53 | let isMRight = x => x > 525
54 |
55 | let handleCurrentPress = (x, y, state) =>
56 | switch (x, y) {
57 | | _ if isMHardLeft(x, y) => {...state, brake: true, left: true}
58 | | _ if isMHardRight(x, y) => {...state, brake: true, right: true}
59 | | _ if isMLeft(x) => {...state, left: true}
60 | | _ if isMRight(x) => {...state, right: true}
61 | | _ if y > breakY => {...state, brake: true}
62 | | _ if 60 > y => {...state, reset: true}
63 | | _ => state
64 | }
65 |
66 | let handleRemovePress = (x, y, state) =>
67 | switch (x, y) {
68 | | _ if isMHardLeft(x, y) => {...state, brake: false, left: false}
69 | | _ if isMHardRight(x, y) => {...state, brake: false, right: false}
70 | | _ if isMLeft(x) => {...state, left: false}
71 | | _ if isMRight(x) => {...state, right: false}
72 | | _ if y > breakY => {...state, brake: false}
73 | | _ => state
74 | }
75 |
76 | let mouseDown = (mousePos, state) => {
77 | let (x, y) = mousePos
78 | handleCurrentPress(x, y, state)
79 | }
80 |
81 | let mouseUp = (mousePos, state) => {
82 | let (x, y) = mousePos
83 | handleRemovePress(x, y, state)
84 | }
85 |
86 | let mouseDragged = (mousePos, previousPosition, state) => {
87 | let (x, y) = mousePos
88 | let (px, py) = previousPosition
89 |
90 | state |> handleRemovePress(px, py) |> handleCurrentPress(x, y)
91 | }
92 |
--------------------------------------------------------------------------------
/src/Index.res:
--------------------------------------------------------------------------------
1 | open Common
2 | open Reprocessing
3 |
4 | type state = {
5 | car: Car.state,
6 | road: Road.state,
7 | control: Control.state,
8 | timer: Timer.state,
9 | score: Score.state,
10 | assets: Screen.Sprite.assets,
11 | }
12 |
13 | let setup = env => {
14 | Env.size(~width, ~height, env)
15 | {
16 | car: Car.init,
17 | road: Road.init,
18 | control: Control.init,
19 | timer: Timer.init(),
20 | score: Score.init,
21 | assets: Screen.Sprite.init(env),
22 | }
23 | }
24 |
25 | let control = state => {
26 | let currentPlane = Road.currentPlane(state.road)
27 | let (currentRoadDirection, currentIncline) = (currentPlane.direction, currentPlane.incline)
28 | let isBrake = Control.isBrake(state.control) || Timer.gameOver(state.timer) ? true : false
29 | let turn = Control.getTurn(state.control)
30 | let car =
31 | Car.turn(turn, state.car)
32 | |> Car.roadEffect(currentRoadDirection, currentIncline)
33 | |> Car.accelerate(isBrake)
34 |
35 | {...state, car: car}
36 | }
37 |
38 | let handleCollisions = state => {
39 | let currentPlane = Road.currentPlane2(state.road)
40 | let car = state.car
41 | let objects = currentPlane.objects
42 |
43 | let objects =
44 | objects |> List.filter(Object.calcHit(car.offset, state.road.position, Common.roadWidth))
45 | let penalty = objects |> List.fold_left((a, b) => Object.speedPenalty(b) +. a, 0.)
46 |
47 | let speed = max(0., car.speed -. penalty)
48 | let car = {...car, speed: speed}
49 |
50 | {...state, car: car}
51 | }
52 |
53 | let updatePosition = state => {
54 | let position = state.road.position +. Car.progression(state.car)
55 | let newRoadState = Road.moveForward(position, state.road)
56 |
57 | let checkpointBonus =
58 | state.road.lastPiece != newRoadState.lastPiece ? Road.checkpointBonus(newRoadState) : 0
59 | let timer = Timer.addTimeInSeconds(checkpointBonus, state.timer)
60 | let startTime =
61 | state.road.lastPiece != newRoadState.lastPiece ? Road.startTime(newRoadState) : 00
62 |
63 | let timer = if (startTime != 0) {
64 | Timer.init(~time=float_of_int(startTime), ())
65 | } else {
66 | timer
67 | }
68 | // let timer = Timer.addTimeInSeconds(checkpointBonus, state.timer)
69 |
70 | {...state, road: newRoadState, timer: timer}
71 | }
72 |
73 | let updateScoreAndTimer = (lastPosition, state) => {
74 | let score = Score.increment(state.road.position -. lastPosition, state.score)
75 | let timer = Timer.reduce(state.timer)
76 |
77 | {...state, score: score, timer: timer}
78 | }
79 |
80 | let drawSky = env => {
81 | Draw.fill(Utils.color(~r=5, ~g=5, ~b=200, ~a=255), env)
82 | Draw.quad(~p1=(0, 0), ~p2=(width, 0), ~p3=(width, height), ~p4=(0, height), env) // might as well fill. This used to be called *after* drawing the road
83 | }
84 |
85 | let drawGame = (state, env) => {
86 | Draw.background(Utils.color(~r=255, ~g=255, ~b=255, ~a=255), env)
87 | drawSky(env)
88 |
89 | let road = Road.Display.make(~offset=state.car.offset, state.road)
90 | let car = Car.Display.make(state.car)
91 | let screen: Screen.t = {road: road, car: car}
92 | Screen.draw(~offset=state.car.offset, ~screen, state.assets, env)
93 |
94 | Draw.fill(Utils.color(~r=25, ~g=25, ~b=25, ~a=255), env)
95 |
96 | let text = Car.speedInMph(state.car)
97 | let mph = "MPH"
98 |
99 | Draw.text(~body=text, ~pos=(420, 20), env)
100 | Draw.text(~body=mph, ~pos=(480, 20), env)
101 | Score.draw(state.score, env)
102 | Timer.draw(state.timer, env)
103 |
104 | state
105 | }
106 |
107 | let draw = (state, env) =>
108 | if Control.isReset(state.control) {
109 | setup(env)
110 | } else {
111 | let lastPosition = state.road.position
112 |
113 | let state = control(state)
114 | let state = handleCollisions(state)
115 | let state = updatePosition(state)
116 | let state = updateScoreAndTimer(lastPosition, state)
117 |
118 | drawGame(state, env)
119 | }
120 |
121 | let keyPressed = (state, env) => {
122 | ...state,
123 | control: Control.keyDown(Env.keyCode(env), state.control),
124 | }
125 | let keyReleased = (state, env) => {
126 | ...state,
127 | control: Control.keyUp(Env.keyCode(env), state.control),
128 | }
129 | let mouseDown = (state, mouseEvent) => {
130 | ...state,
131 | control: Control.mouseDown(Env.mouse(mouseEvent), state.control),
132 | }
133 | let mouseUp = (state, mouseEvent) => {
134 | ...state,
135 | control: Control.mouseUp(Env.mouse(mouseEvent), state.control),
136 | }
137 | let mouseDragged = (state, mouseEvent) => {
138 | ...state,
139 | control: Control.mouseDragged(Env.mouse(mouseEvent), Env.pmouse(mouseEvent), state.control),
140 | }
141 |
142 | run(
143 | ~setup,
144 | ~screen="game",
145 | ~draw,
146 | ~keyPressed,
147 | ~keyReleased,
148 | ~mouseDown,
149 | ~mouseUp,
150 | ~mouseDragged,
151 | (),
152 | )
153 |
--------------------------------------------------------------------------------
/src/IndexHot.res:
--------------------------------------------------------------------------------
1 | let _ = Reprocessing.hotreload("src/index.re")
2 | ()
3 |
--------------------------------------------------------------------------------
/src/Object.res:
--------------------------------------------------------------------------------
1 | type objectType =
2 | | SIGN_RIGHT
3 | | SIGN_LEFT
4 | | TREE
5 | | STONE
6 | | POST
7 |
8 | type state = {
9 | objectType: objectType,
10 | offset: float,
11 | z: float,
12 | size: (int, int),
13 | hitbox: (float, float),
14 | }
15 |
16 | let calcHit = (playerPosition, distance, roadWidth, obj) => {
17 | let carSizeFactor = 55. /. roadWidth
18 | let playerOffset = playerPosition *. -1.
19 |
20 | let (playerOff1, playerOff2) = (playerOffset -. carSizeFactor, playerOffset +. carSizeFactor)
21 | let adj = mod_float(distance, 40. *. 2.)
22 | let playerTravel = adj >= 40. ? adj -. 40. : adj
23 |
24 | let {objectType: _, offset, z, size: _, hitbox: (hbX, hbY)} = obj
25 | let factor = hbX /. roadWidth
26 |
27 | let x1 = offset -. factor /. 2.
28 | let x2 = offset +. factor /. 2.
29 | let hbY = hbY *. 0.5
30 |
31 | let y1 = (z -. hbY) *. 0.5
32 | let y2 = z
33 | let inHbX = playerOff2 >= x1 && playerOff1 <= x2
34 | let inHbY = playerTravel >= y1 && playerTravel <= y2
35 |
36 | inHbX && inHbY
37 | }
38 |
39 | let speedPenalty = obj =>
40 | switch obj.objectType {
41 | | SIGN_RIGHT
42 | | SIGN_LEFT => 14.
43 | | TREE => {
44 | let (x, _) = obj.size
45 | x > 100 ? 15. : 6.
46 | }
47 | | STONE => 22.
48 | | POST => 9.
49 | }
50 |
51 | module Display = {
52 | type t = {
53 | offset: float,
54 | height: float,
55 | width: float,
56 | z: float,
57 | objectType: objectType,
58 | }
59 |
60 | let make = (~z=0., ~offset, ~height, ~width, objectType) => {
61 | z: z,
62 | height: height,
63 | width: width,
64 | offset: offset,
65 | objectType: objectType,
66 | }
67 |
68 | let make = (obj: state) => {
69 | let (width, height) = obj.size
70 |
71 | make(
72 | ~offset=obj.offset,
73 | ~height=float_of_int(height),
74 | ~width=float_of_int(width),
75 | obj.objectType,
76 | )
77 | }
78 | }
79 |
80 | module Prefabs = {
81 | let makeSignRight = {
82 | objectType: SIGN_RIGHT,
83 | offset: -1.25,
84 | z: 16.,
85 | size: (96, 96),
86 | hitbox: (48., 4.),
87 | }
88 | let makeSignLeft = {
89 | objectType: SIGN_LEFT,
90 | offset: 1.25,
91 | z: 16.,
92 | size: (92, 92),
93 | hitbox: (48., 4.),
94 | }
95 | let makeTree = offset => {
96 | objectType: TREE,
97 | offset: offset,
98 | z: 16.,
99 | size: (128, 216),
100 | hitbox: (64., 4.),
101 | }
102 | let smallTree = offset => {
103 | objectType: TREE,
104 | offset: offset,
105 | z: 16.,
106 | size: (64, 108),
107 | hitbox: (32., 3.),
108 | }
109 | let makeStone = offset => {
110 | objectType: STONE,
111 | offset: offset,
112 | z: 16.,
113 | size: (64, 64),
114 | hitbox: (48., 4.),
115 | }
116 | let makePost = offset => {
117 | objectType: POST,
118 | offset: offset,
119 | z: 16., // 6, 19
120 | size: (12, 38),
121 | hitbox: (4., 4.),
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/Road.res:
--------------------------------------------------------------------------------
1 | /* Road constants */
2 | let baseLength = 40.
3 |
4 | type state = {
5 | position: float,
6 | lastPiece: int,
7 | track: Track.state,
8 | }
9 |
10 | let currentPlane = state => Track.head(state.track)
11 | let currentPlane2 = state => state.track |> Track.tail |> List.hd
12 |
13 | let moveForward = (newPosition, state) =>
14 | float_of_int(state.lastPiece) *. baseLength -. newPosition <= 0.
15 | ? {
16 | lastPiece: state.lastPiece + 1,
17 | position: newPosition,
18 | track: Track.progress(state.track),
19 | }
20 | : {...state, position: newPosition}
21 |
22 | let onCheckpoint = state => state.track |> Track.head |> Track.isCheckpoint
23 |
24 | let checkpointBonus = state =>
25 | state.track
26 | |> Track.head
27 | |> (
28 | p =>
29 | switch p.direction {
30 | | Track.Checkpoint(t) => t
31 | | _ => 0
32 | }
33 | )
34 | let startTime = state =>
35 | state.track
36 | |> Track.head
37 | |> (
38 | p =>
39 | switch p.direction {
40 | | Track.Start(t) => t
41 | | _ => 0
42 | }
43 | )
44 | let init = {position: 0., track: Track.init, lastPiece: 1}
45 |
46 | %%private(
47 | let findInitialCoordinates = (offset, state) => {
48 | let (isLight, remainder) = {
49 | let adj = mod_float(state.position, baseLength *. 2.)
50 | adj >= baseLength ? (true, adj -. baseLength) : (false, adj)
51 | }
52 | let x0 = Common.centrePoint -. Common.roadWidth /. 2. +. offset
53 | let x1 = Common.centrePoint +. Common.roadWidth /. 2. +. offset
54 | (x0, x1, remainder, isLight)
55 | }
56 | )
57 |
58 | module Display = {
59 | type colour = {
60 | r: int,
61 | g: int,
62 | b: int,
63 | a: int,
64 | }
65 | type t = {
66 | x: float,
67 | y: float,
68 | z: float,
69 | previous: (float, float, float),
70 | colour: colour,
71 | terrainColour: colour,
72 | objects: list,
73 | }
74 |
75 | %%private(let red = {r: 150, g: 80, b: 80, a: 255})
76 |
77 | %%private(let lightGrey = {r: 78, g: 78, b: 78, a: 255})
78 | %%private(let darkGrey = {r: 70, g: 70, b: 70, a: 255})
79 |
80 | %%private(let roadLightGrey = {r: 62, g: 62, b: 62, a: 255})
81 | %%private(let roadDarkGrey = {r: 56, g: 56, b: 56, a: 255})
82 |
83 | %%private(let roadBrown = {r: 84, g: 66, b: 33, a: 255})
84 | %%private(let roadDarkBrown = {r: 70, g: 55, b: 30, a: 255})
85 |
86 | %%private(let lightGreen = {r: 45, g: 140, b: 30, a: 255})
87 | %%private(let darkGreen = {r: 30, g: 120, b: 30, a: 255})
88 |
89 | %%private(let lightBrown = {r: 82, g: 59, b: 32, a: 255})
90 | %%private(let darkBrown = {r: 70, g: 50, b: 30, a: 255})
91 |
92 | %%private(let lightBlue = {r: 45, g: 40, b: 140, a: 255})
93 | %%private(let darkBlue = {r: 36, g: 32, b: 130, a: 255})
94 |
95 | let make = (~offset, state) => {
96 | let (_, _, remainder, isLight) = findInitialCoordinates(offset, state)
97 | // let iOffset = int_of_float(offset *. 0.4) /* interesting */
98 | let remainder = baseLength -. remainder
99 | let convert = (~remainder, ~isDark=isLight, track) => {
100 | let isDark = ref(isDark)
101 | let previous = ref(None)
102 | let ddx = ref(0.)
103 | track |> List.mapi((i, plane: Track.plane) => {
104 | let i = float_of_int(i)
105 | let {direction, objects, incline, roadSurface, groundSurface} = plane
106 |
107 | let objects = objects |> List.map(Object.Display.make)
108 |
109 | // Calc position
110 | let findXyz = (~previous, ~remainder, ~direction, ~incline, ~ddx) => {
111 | let curve = switch direction {
112 | | Track.Left(curve) => i == 0. ? remainder /. baseLength *. curve *. -2. : curve *. -2.
113 | | Right(curve) => i == 0. ? remainder /. baseLength *. curve *. 2. : curve *. 2.
114 | | _ => 0.
115 | }
116 | let curve = curve +. ddx
117 | let ddx = curve
118 | let prev = switch previous {
119 | | Some(xyz) => xyz
120 | | None => (0., 50., 0.)
121 | }
122 | let (px, py, _pz) = prev
123 |
124 | let x = px +. curve
125 | let yFactor = 0.36 *. incline
126 | let y = i == 0. ? py +. yFactor *. remainder /. baseLength : py +. yFactor
127 | let z = i *. baseLength +. remainder
128 |
129 | ((x, y, z), ddx, prev)
130 | }
131 |
132 | let ((x, y, z), newddx, prev) = findXyz(
133 | ~previous=previous.contents,
134 | ~remainder,
135 | ~direction,
136 | ~incline,
137 | ~ddx=ddx.contents,
138 | )
139 |
140 | previous := Some((x, y, z))
141 | ddx := newddx
142 |
143 | let isCheckpoint = Track.isCheckpoint(plane)
144 |
145 | let dark = isDark.contents
146 |
147 | let terrainColour = switch groundSurface {
148 | | Grass => dark ? darkGreen : lightGreen
149 | | Soil => dark ? darkBrown : lightBrown
150 | | Water => dark ? darkBlue : lightBlue
151 | | Gravel => dark ? darkGrey : lightGrey
152 | }
153 |
154 | let colour = switch roadSurface {
155 | | _ when isCheckpoint => red
156 | | Tarmac when dark => roadLightGrey
157 | | Tarmac => roadDarkGrey
158 | | Dirt when dark => roadBrown
159 | | Dirt => roadDarkBrown
160 | }
161 |
162 | let result = {
163 | x: x,
164 | y: y,
165 | z: z,
166 | previous: prev,
167 | colour: colour,
168 | terrainColour: terrainColour,
169 | objects: objects,
170 | }
171 |
172 | isDark := !isDark.contents
173 | result
174 | })
175 | }
176 |
177 | convert(~remainder, ~isDark=isLight, state.track.track)
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/src/Score.res:
--------------------------------------------------------------------------------
1 | type state = {score: float}
2 |
3 | let scoreString = state => state.score /. 10. |> int_of_float |> string_of_int
4 |
5 | let increment = (x, state) => {score: state.score +. x}
6 | let init = {score: 0.}
7 |
8 | let draw = (state, env) => {
9 | let score = scoreString(state)
10 | Reprocessing.Draw.text(~body=score, ~pos=(60, 20), env)
11 | }
12 |
--------------------------------------------------------------------------------
/src/Screen.res:
--------------------------------------------------------------------------------
1 | type t = {
2 | car: Car.Display.t,
3 | road: list,
4 | }
5 |
6 | let cameraHeight = ref(55.)
7 |
8 | let cameraDepth = Common.cameraDepth
9 |
10 | let projectToScreen = (~offset, x, y, z) => {
11 | let iOffset = Common.roadWidth /. 2. *. offset *. 0.04
12 | let cameraX = x +. iOffset
13 | let cameraY = y -. cameraHeight.contents
14 | let cameraZ = z -. 0. // - cameraZ
15 | let cameraZ = cameraZ == 0. ? 1. : cameraZ
16 |
17 | let scale = cameraDepth /. cameraZ
18 |
19 | let screenX = Common.centrePoint +. scale *. cameraX *. Common.centrePoint
20 | let screenY = Common.centreHeight -. scale *. cameraY *. Common.centreHeight
21 |
22 | let roadWidth = scale *. Common.roadWidth *. (Common.widthF /. 100.)
23 |
24 | let scale = scale *. 8. // objects all appearing small
25 | (screenX, screenY, roadWidth, scale)
26 | }
27 |
28 | module Sprite = {
29 | open Reprocessing
30 | type carAssets = {
31 | straight: Reprocessing_Common.imageT,
32 | leftTurn: Reprocessing_Common.imageT,
33 | heavyLeftTurn: Reprocessing_Common.imageT,
34 | rightTurn: Reprocessing_Common.imageT,
35 | heavyRightTurn: Reprocessing_Common.imageT,
36 | }
37 | type assets = {
38 | roadSignRight: Reprocessing_Common.imageT,
39 | roadSignLeft: Reprocessing_Common.imageT,
40 | tree: Reprocessing_Common.imageT,
41 | stone: Reprocessing_Common.imageT,
42 | post: Reprocessing_Common.imageT,
43 | car: carAssets,
44 | }
45 | type carState =
46 | | Straight
47 | | LeftTurn
48 | | HeavyLeftTurn
49 | | RightTurn
50 | | HeavyRightTurn
51 |
52 | type objectType =
53 | | SIGN_RIGHT
54 | | SIGN_LEFT
55 | | TREE
56 | | STONE
57 | | POST
58 | | CAR(carState)
59 |
60 | type t = {
61 | x: float,
62 | y: float,
63 | height: float,
64 | width: float,
65 | objectType: objectType,
66 | }
67 |
68 | let fromObject = o =>
69 | switch o {
70 | | Object.SIGN_RIGHT => SIGN_RIGHT
71 | | SIGN_LEFT => SIGN_LEFT
72 | | TREE => TREE
73 | | STONE => STONE
74 | | POST => POST
75 | }
76 |
77 | let fromCar = c =>
78 | switch c {
79 | | Car.Display.Straight => CAR(Straight)
80 | | LeftTurn => CAR(LeftTurn)
81 | | HeavyLeftTurn => CAR(HeavyLeftTurn)
82 | | RightTurn => CAR(RightTurn)
83 | | HeavyRightTurn => CAR(HeavyRightTurn)
84 | }
85 |
86 | let loadAssets = env => {
87 | let loadImage = file => Draw.loadImage(~filename=file, ~isPixel=true, env)
88 |
89 | {
90 | roadSignLeft: loadImage("assets/roadsign_left.png"),
91 | roadSignRight: loadImage("assets/roadsign.png"),
92 | tree: loadImage("assets/tree.png"),
93 | stone: loadImage("assets/stone.png"),
94 | post: loadImage("assets/post.png"),
95 | car: {
96 | straight: loadImage("assets/car_1.png"),
97 | leftTurn: loadImage("assets/car_2.png"),
98 | heavyLeftTurn: loadImage("assets/car_3.png"),
99 | rightTurn: loadImage("assets/car_4.png"),
100 | heavyRightTurn: loadImage("assets/car_5.png"),
101 | },
102 | }
103 | }
104 |
105 | let init = env => loadAssets(env)
106 | let draw = (~sprite, assets, env) => {
107 | let {x, y, height, width, objectType} = sprite
108 | let pos = (x -. width /. 2., y)
109 | let draw = Draw.imagef(_, ~pos, ~width, ~height, env)
110 |
111 | switch objectType {
112 | | SIGN_RIGHT => draw(assets.roadSignRight)
113 | | SIGN_LEFT => draw(assets.roadSignLeft)
114 | | TREE => draw(assets.tree)
115 | | STONE => draw(assets.stone)
116 | | POST => draw(assets.post)
117 | | CAR(state) =>
118 | switch state {
119 | | Straight => draw(assets.car.straight)
120 | | LeftTurn => draw(assets.car.leftTurn)
121 | | HeavyLeftTurn => draw(assets.car.heavyLeftTurn)
122 | | RightTurn => draw(assets.car.rightTurn)
123 | | HeavyRightTurn => draw(assets.car.heavyRightTurn)
124 | }
125 | }
126 | }
127 | }
128 | module Quad = {
129 | type t = {
130 | x: float,
131 | y: float,
132 | w: float,
133 | previous: (float, float, float),
134 | colour: Road.Display.colour,
135 | terrainColour: Road.Display.colour,
136 | objects: list,
137 | }
138 |
139 | let make = (~offset, road: Road.Display.t): t => {
140 | let {x, y, z, previous, colour, terrainColour, objects} = road
141 |
142 | let (x, y, w, scale) = projectToScreen(~offset, x, y, z)
143 | let (px, py, pz) = previous
144 | let (px, py, pw, _) = projectToScreen(~offset, px, py, pz)
145 | let previous = (px, py, pw)
146 | // This places objects in the middle. Using x,y,z puts them at the back and px... at the front
147 | let (ox, oy, ow) = (x -. (x -. px) /. 2., y -. (y -. py) /. 2., w -. (w -. pw) /. 2.)
148 |
149 | let objects = objects |> List.map((o: Object.Display.t) => {
150 | Sprite.x: ox +. ow *. o.offset,
151 | y: oy -. o.height *. scale,
152 | height: o.height *. scale,
153 | width: o.width *. scale,
154 | objectType: o.objectType |> Sprite.fromObject,
155 | })
156 |
157 | {
158 | x: x,
159 | y: y,
160 | w: w,
161 | previous: previous,
162 | colour: colour,
163 | terrainColour: terrainColour,
164 | objects: objects,
165 | }
166 | }
167 |
168 | let draw = (quad, assets, env) => {
169 | let {x, y, w, previous, colour, terrainColour} = quad
170 | let (px, py, pw) = previous
171 | open Reprocessing
172 |
173 | if abs_float(py) > abs_float(y) {
174 | Draw.fill(
175 | Utils.color(~r=terrainColour.r, ~g=terrainColour.g, ~b=terrainColour.b, ~a=terrainColour.a),
176 | env,
177 | )
178 | Draw.quadf(~p1=(0., py), ~p2=(Common.widthF, py), ~p3=(Common.widthF, y), ~p4=(0., y), env)
179 |
180 | Draw.fill(Utils.color(~r=colour.r, ~g=colour.g, ~b=colour.b, ~a=colour.a), env)
181 | Draw.quadf(~p1=(px -. pw, py), ~p2=(px +. pw, py), ~p3=(x +. w, y), ~p4=(x -. w, y), env)
182 | let (infront, behind) = quad.objects |> List.partition((a: Sprite.t) => a.y < 276.)
183 | let _infront = infront |> List.map(sprite => Sprite.draw(~sprite, assets, env))
184 | behind
185 | } else {
186 | list{}
187 | }
188 | }
189 | }
190 |
191 | let makeCar = (car: Car.Display.t): Sprite.t => {
192 | {
193 | Sprite.x: Common.centrePoint,
194 | y: Common.heightF -. car.height +. 1.,
195 | height: car.height,
196 | width: car.width,
197 | objectType: car.asset |> Sprite.fromCar,
198 | }
199 | }
200 |
201 | let draw = (~offset, ~screen, assets, env) => {
202 | let {road, car} = screen
203 |
204 | let projectedRoad =
205 | road->Belt.List.take(Common.planes)->Belt.Option.getExn |> List.map(Quad.make(~offset))
206 |
207 | let projectedCar = car->makeCar
208 | let behind =
209 | projectedRoad
210 | |> List.sort((_a: Quad.t, b: Quad.t) => int_of_float(b.y))
211 | |> List.map(quad => {
212 | Quad.draw(quad, assets, env)
213 | })
214 | |> List.flatten
215 |
216 | Sprite.draw(~sprite=projectedCar, assets, env)
217 |
218 | behind->Belt.List.forEach(sprite => Sprite.draw(~sprite, assets, env))
219 | }
220 |
--------------------------------------------------------------------------------
/src/Timer.res:
--------------------------------------------------------------------------------
1 | type state = {remainingTime: float}
2 |
3 | let remainingTimeString = state =>
4 | state.remainingTime /. Common.frameRate |> int_of_float |> string_of_int
5 |
6 | let addTimeInSeconds = (seconds, state) => {
7 | let timeInFrames = float_of_int(seconds) *. Common.frameRate
8 | let remainingTime = timeInFrames +. state.remainingTime
9 | {remainingTime: remainingTime}
10 | }
11 |
12 | let reduce = state =>
13 | 0. >= state.remainingTime ? {remainingTime: 0.} : {remainingTime: state.remainingTime -. 1.}
14 | let gameOver = state => 0. >= state.remainingTime
15 |
16 | let init = (~time=59.5, ()) => {remainingTime: time *. Common.frameRate}
17 |
18 | let draw = (state, env) => {
19 | let time = remainingTimeString(state)
20 | Reprocessing.Draw.text(~body=time, ~pos=(Common.width / 2, 20), env)
21 | }
22 |
--------------------------------------------------------------------------------
/src/Track.res:
--------------------------------------------------------------------------------
1 | type direction =
2 | | Straight
3 | | Left(float)
4 | | Right(float)
5 | | Checkpoint(int)
6 | | Start(int)
7 |
8 | let bunchOfSmallTrees = (offset1, offset2, offset3) => list{
9 | Object.Prefabs.smallTree(offset1),
10 | Object.Prefabs.smallTree(offset2),
11 | Object.Prefabs.smallTree(offset3),
12 | }
13 |
14 | let edgePosts = list{Object.Prefabs.makePost(1.), Object.Prefabs.makePost(-1.)}
15 |
16 | type roadSurface =
17 | | Tarmac
18 | | Dirt
19 |
20 | type groundSurface =
21 | | Grass
22 | | Soil
23 | | Water
24 | | Gravel
25 |
26 | type plane = {
27 | direction: direction,
28 | objects: list,
29 | incline: float,
30 | roadSurface: roadSurface,
31 | groundSurface: groundSurface,
32 | }
33 |
34 | type state = {track: list}
35 |
36 | let demoTrack = {
37 | open Object.Prefabs
38 |
39 | let ec1 = 0.08
40 | let ec2 = 0.16
41 | let ec3 = 0.20
42 | let ec4 = 0.24
43 | let mc1 = 0.28
44 | let mc2 = 0.32
45 | let mc3 = 0.4
46 | let mc4 = 0.48
47 | let hc1 = 0.54
48 | let hc2 = 0.6
49 | let hc3 = 0.68
50 | let hc4 = 0.72
51 | let hp1 = 0.8
52 |
53 | let makeCheckpoint = (
54 | ~incline=0.,
55 | ~roadSurface=Tarmac,
56 | ~groundSurface=Grass,
57 | duration: int,
58 | ) => list{
59 | {
60 | direction: Checkpoint(duration),
61 | objects: list{},
62 | incline: incline,
63 | roadSurface: roadSurface,
64 | groundSurface: groundSurface,
65 | },
66 | }
67 | let makeStart = (
68 | ~incline=0.,
69 | ~roadSurface=Tarmac,
70 | ~groundSurface=Grass,
71 | timelimit: int,
72 | ) => list{
73 | {
74 | direction: Start(timelimit),
75 | objects: list{},
76 | incline: incline,
77 | roadSurface: roadSurface,
78 | groundSurface: groundSurface,
79 | },
80 | }
81 | let make = (
82 | ~times=1,
83 | ~objects=list{},
84 | ~incline=0.,
85 | ~roadSurface=Tarmac,
86 | ~groundSurface=Grass,
87 | direction,
88 | ) =>
89 | Array.make(
90 | times,
91 | {
92 | direction: direction,
93 | objects: objects,
94 | incline: incline,
95 | roadSurface: roadSurface,
96 | groundSurface: groundSurface,
97 | },
98 | ) |> Array.to_list
99 |
100 | let track =
101 | list{
102 | make(~times=3, Straight),
103 | make(~times=2, ~incline=0.5, Straight),
104 | make(~times=1, ~incline=-1., Straight),
105 | make(~times=1, ~incline=-2., ~objects=list{makeStone(0.5)}, Straight),
106 | make(~times=1, ~objects=list{smallTree(1.17), makeTree(1.55)}, ~incline=-3., Straight),
107 | make(~times=1, ~incline=-4., Straight),
108 | make(~times=1, ~incline=-5., Straight),
109 | make(~times=8, ~incline=-6., ~roadSurface=Dirt, ~groundSurface=Water, ~objects=list{}, Straight),
110 | make(~times=8, ~incline=-5., ~roadSurface=Tarmac, ~groundSurface=Soil, ~objects=list{}, Straight),
111 | make(~times=4, ~incline=-4., ~objects=bunchOfSmallTrees(1.3, 1.5, 1.7), Straight),
112 | make(~times=2, ~incline=-3., Straight),
113 | make(~times=2, ~incline=-2., ~objects=bunchOfSmallTrees(1.35, 1.5, 1.65), Straight),
114 | make(~times=2, ~incline=-1., ~objects=list{makeTree(1.6)}, Straight),
115 | make(~times=2, ~objects=list{smallTree(1.35), makeTree(1.95)}, Right(ec2)),
116 | make(~times=2, ~objects=bunchOfSmallTrees(-1.3, 1.5, -1.7), Right(ec2)),
117 | make(~times=2, ~objects=list{smallTree(1.17), makeTree(1.55)}, Right(ec2)),
118 | make(~times=1, ~incline=1., Straight),
119 | make(~times=2, ~incline=2., Straight),
120 | make(~times=9, ~incline=3., Straight),
121 | make(~times=6, ~incline=2., Straight),
122 | make(~times=3, ~incline=0.5, Straight),
123 | make(~times=16, Left(ec1)),
124 | makeCheckpoint(9),
125 | make(~times=16, Left(ec1)),
126 | make(~times=6, ~incline=0.8, Left(ec2)),
127 | make(~times=8, ~incline=1.5, ~objects=list{makePost(0.), makeSignLeft}, Left(ec4)),
128 | make(~times=8, ~incline=3.7, ~objects=list{makePost(0.), makeSignLeft}, Left(mc2)),
129 | make(~times=8, ~incline=4.2, ~objects=list{makePost(0.), makeSignRight}, Right(ec4)),
130 | make(~times=12, ~incline=6.1, ~objects=list{makeSignRight}, Right(mc2)),
131 | make(~times=4, ~incline=4.2, ~objects=list{makeSignRight, makeTree(-1.65)}, Right(ec4)),
132 | make(~times=6, ~incline=3.2, ~objects=list{makeSignRight}, Right(ec4)),
133 | make(~times=4, ~incline=1.2, Right(ec4)),
134 | make(~times=4, ~objects=list{makeSignRight}, Right(ec4)),
135 | make(~times=6, Straight),
136 | make(~times=18, ~objects=list{makeSignRight}, Right(ec2)),
137 | make(~times=2, ~incline=-0.2, Straight),
138 | make(~times=10, ~incline=-0.8, Straight),
139 | make(~times=18, ~incline=-1.2, Right(ec1)),
140 | make(~times=10, ~incline=-0.7, Right(ec2)),
141 | make(~times=2, ~incline=-0.3, Right(ec2)),
142 | make(~times=12, Right(ec4)),
143 | make(~times=12, ~objects=list{makeSignRight}, Right(mc2)),
144 | make(~times=2, ~objects=list{makeStone(1.55)}, Right(mc3)),
145 | make(~times=4, ~incline=-0.5, Straight),
146 | make(~times=2, ~objects=list{makeTree(-1.25), makeTree(1.25)}, ~incline=-1.5, Straight),
147 | make(~times=2, ~objects=list{makeTree(-1.35), makeTree(1.35)}, ~incline=-1.5, Straight),
148 | make(~times=2, ~incline=-1.5, Straight),
149 | make(
150 | ~times=2,
151 | ~objects=list{makeTree(-1.25), makeTree(-1.45), makeTree(1.25), makeTree(1.45)},
152 | ~incline=-1.5,
153 | Straight,
154 | ),
155 | make(~times=4, ~incline=-0.5, Straight),
156 | make(~times=8, Left(ec1)),
157 | make(~times=1, ~objects=list{makeStone(0.9), makeStone(0.6), makeStone(0.3)}, Left(ec1)),
158 | make(~times=1, ~objects=list{makeStone(0.1)}, Left(ec1)),
159 | make(~times=8, Left(ec1)),
160 | make(
161 | ~times=1,
162 | ~objects=list{makeStone(-0.85), makeStone(-0.65), makeStone(-0.45)},
163 | Left(ec1),
164 | ),
165 | make(~times=1, ~objects=list{makeStone(-0.1)}, Left(ec1)),
166 | make(~times=4, Left(ec1)),
167 | make(~times=6, Straight),
168 | make(~times=6, Straight),
169 | make(~times=6, ~incline=0.6, Straight),
170 | make(~times=6, ~incline=1.8, ~objects=list{makeSignLeft}, Left(mc3)),
171 | make(~times=3, ~incline=0.3, ~objects=list{makeSignLeft}, Left(mc3)),
172 | make(~times=6, ~incline=-0.2, ~objects=list{makeSignLeft}, Left(hc2)),
173 | make(~times=6, Straight),
174 | make(~times=1, ~objects=bunchOfSmallTrees(1.3, 1.5, 1.7), Straight),
175 | make(~times=1, ~objects=bunchOfSmallTrees(-1.25, -1.5, -1.75), Straight),
176 | make(~times=1, ~objects=bunchOfSmallTrees(1.2, 1.4, 1.6), Straight),
177 | make(~times=1, ~objects=bunchOfSmallTrees(-1.2, -1.4, -1.6), Straight),
178 | make(~times=1, ~objects=bunchOfSmallTrees(1.3, 1.5, 1.7), Straight),
179 | make(~times=1, ~incline=0.4, ~objects=bunchOfSmallTrees(-1.2, -1.5, -1.7), Straight),
180 | make(~times=1, ~incline=0.9, Right(hc3)),
181 | make(~times=1, ~incline=1.3, Right(hc4)),
182 | make(~times=4, ~incline=2.8, Right(hp1)),
183 | make(~times=1, ~incline=1.7, Right(hc4)),
184 | make(~times=1, ~incline=0.5, Right(hc3)),
185 | make(~times=4, ~incline=0.2, Straight),
186 | make(~times=1, ~objects=list{makeStone(1.4), makeStone(1.75)}, Straight),
187 | make(~times=1, ~objects=list{makeStone(1.65)}, Straight),
188 | make(~times=12, Left(hc2)),
189 | make(~times=6, Straight),
190 | makeCheckpoint(9),
191 | make(
192 | ~times=6,
193 | ~objects=list{smallTree(-1.35), makeTree(-1.9), smallTree(1.35), makeTree(1.9)},
194 | Straight,
195 | ),
196 | make(~times=36, ~objects=list{makeSignRight}, Right(mc2)),
197 | make(~times=12, Left(hc2)),
198 | make(~times=12, Straight),
199 | make(~times=18, ~objects=list{makeSignLeft}, Left(hc2)),
200 | make(~times=6, ~objects=list{makeSignLeft}, Straight),
201 | make(~times=6, Left(1.)),
202 | make(~times=12, Straight),
203 | make(~times=2, ~incline=-1., Straight),
204 | make(~times=2, ~incline=-2., Straight),
205 | make(~times=36, ~incline=-2.4, Right(mc3)),
206 | make(~times=2, ~incline=-2., Straight),
207 | make(~times=2, ~incline=-1., Straight),
208 | make(~times=6, Straight),
209 | makeCheckpoint(9),
210 | make(~times=3, Straight),
211 | make(~times=2, ~incline=0.5, Straight),
212 | make(~times=1, ~incline=-1., Straight),
213 | make(~times=1, ~incline=-2., Straight),
214 | make(~times=1, ~objects=list{smallTree(1.17), makeTree(1.55)}, ~incline=-3., Straight),
215 | make(~times=1, ~incline=-4., ~objects=list{makeStone(-1.75), makeStone(-1.5)}, Straight),
216 | make(~times=1, ~incline=-5., ~objects=list{makeStone(1.75)}, Straight),
217 | make(~times=8, ~incline=-6., Straight),
218 | make(~times=6, ~objects=list{smallTree(1.35), makeStone(1.95)}, ~incline=-7., Right(ec2)),
219 | make(~times=14, ~incline=-7., Left(ec2)),
220 | make(~times=8, ~incline=-7.5, Straight),
221 | make(~times=8, ~incline=-8., Right(ec2)),
222 | make(~times=12, ~objects=list{makeSignRight}, ~incline=-8.5, Right(ec4)),
223 | make(~times=8, ~incline=-8., Right(mc2)),
224 | make(~times=6, ~objects=list{makeStone(1.95)}, ~incline=-7., Right(ec2)),
225 | make(~times=8, ~incline=-5., Straight),
226 | make(~times=4, ~incline=-4., ~objects=bunchOfSmallTrees(1.3, 1.5, 1.7), Straight),
227 | make(~times=2, ~incline=-3., Straight),
228 | make(~times=2, ~incline=-2., ~objects=bunchOfSmallTrees(1.35, 1.5, 1.65), Straight),
229 | make(~times=2, ~incline=-1., ~objects=list{makeTree(1.6)}, Straight),
230 | make(~times=2, ~objects=list{smallTree(1.35), makeTree(1.95)}, Right(ec2)),
231 | make(~times=2, ~objects=bunchOfSmallTrees(-1.3, 1.5, -1.7), Right(ec2)),
232 | make(~times=2, ~objects=list{smallTree(1.17), makeTree(1.55)}, Right(ec2)),
233 | make(~times=1, ~incline=1., Straight),
234 | make(~times=2, ~incline=1.5, Straight),
235 | make(~times=4, ~incline=2.4, Straight),
236 | make(~times=9, ~incline=3.5, Straight),
237 | make(~times=6, ~incline=2., Straight),
238 | make(~times=3, ~incline=0.5, Straight),
239 | make(~times=16, Left(ec1)),
240 | make(~times=8, Left(ec4)),
241 | make(~times=6, ~incline=1., Left(ec1)),
242 | make(~times=6, ~objects=list{makePost(0.)}, ~incline=0.2, Straight),
243 | make(~times=8, ~objects=list{makePost(0.)}, ~incline=0.8, Right(ec4)),
244 | make(~times=8, ~incline=2.2, ~objects=list{makePost(0.), makeSignRight}, Right(mc3)),
245 | make(~times=2, ~incline=3.2, Straight),
246 | make(~times=8, ~incline=5.2, Straight),
247 | make(~times=6, ~incline=6.1, Straight),
248 | make(~times=4, ~incline=5.8, ~objects=list{makePost(0.)}, Left(ec1)),
249 | make(~times=8, ~incline=6.5, ~objects=list{makePost(0.)}, Left(ec4)),
250 | make(~times=8, ~incline=7.5, ~objects=list{makeSignLeft}, Left(mc3)),
251 | make(~times=2, ~incline=8.8, Straight),
252 | makeCheckpoint(~incline=9.2, 6),
253 | make(~times=3, ~incline=9.9, ~objects=list{makePost(0.)}, Left(ec4)),
254 | make(~times=4, ~incline=12.4, ~objects=list{makePost(0.)}, Left(hc2)),
255 | make(~times=4, ~incline=9.4, Left(mc2)),
256 | make(~times=4, ~incline=8.4, ~objects=list{makePost(0.)}, Left(ec1)),
257 | make(~times=4, ~incline=6.2, ~objects=list{makePost(0.)}, Straight),
258 | make(~times=4, ~incline=4.2, Straight),
259 | make(~times=2, ~incline=5.4, Straight),
260 | make(~times=4, ~incline=6.2, Right(ec1)),
261 | make(~times=4, ~incline=6.6, Right(ec2)),
262 | make(~times=8, ~incline=7.1, Right(ec4)),
263 | make(~times=8, ~incline=6.9, Right(mc2)),
264 | make(~times=8, ~incline=6.4, ~objects=list{makePost(0.)}, Right(mc3)),
265 | make(~times=8, ~incline=6.1, ~objects=list{makePost(0.), makeSignRight}, Right(hc2)),
266 | make(~times=4, ~incline=5.2, Straight),
267 | make(~times=2, ~incline=4.7, Straight),
268 | make(~times=2, ~incline=4.4, Straight),
269 | make(~times=6, ~incline=4.2, Straight),
270 | make(~times=1, ~incline=4.5, ~objects=list{makeStone(-0.2)}, Straight),
271 | make(~times=1, ~incline=4.5, ~objects=list{makeStone(-0.4)}, Straight),
272 | make(~times=6, ~incline=5.1, Left(ec4)),
273 | make(~times=4, ~incline=6.2, Straight),
274 | make(~times=4, ~incline=4.2, Straight),
275 | make(~times=2, ~incline=2.2, Straight),
276 | make(~times=1, ~incline=1.2, ~objects=list{makeStone(-0.8)}, Straight),
277 | make(~times=1, ~incline=1.2, Straight),
278 | make(~times=1, ~incline=0.5, Straight),
279 | make(
280 | ~times=1,
281 | ~incline=0.,
282 | ~objects=list{makeStone(0.3), makeStone(0.6), makeStone(0.9)},
283 | Straight,
284 | ),
285 | make(~times=1, ~incline=-0.5, Straight),
286 | makeCheckpoint(~incline=-1.3, 9),
287 | make(~times=1, ~incline=-1.2, Straight),
288 | make(~times=1, ~incline=-1.2, ~objects=list{makeStone(-0.2)}, Straight),
289 | make(~times=8, ~incline=-2.4, Left(ec4)),
290 | make(~times=12, ~incline=-3.6, Straight),
291 | make(~times=8, ~incline=-2.4, Straight),
292 | make(~times=8, ~incline=-1.2, Straight),
293 | make(~times=4, ~incline=0., Straight),
294 | make(~times=4, ~incline=1., Straight),
295 | make(~times=4, ~incline=4., Straight),
296 | make(~times=12, ~incline=5., Straight),
297 | make(~times=4, ~incline=5.4, Straight),
298 | make(~times=4, ~incline=3.2, Straight),
299 | make(~times=4, ~incline=1.1, Straight),
300 | make(~times=8, ~incline=0.2, ~objects=list{makeSignRight}, Right(mc3)),
301 | make(~times=8, ~incline=-2.2, Right(ec4)),
302 | make(~times=8, ~incline=-0.2, Straight),
303 | make(~times=4, ~incline=1.2, Straight),
304 | make(~times=4, ~incline=0.2, Straight),
305 | make(~times=4, ~incline=-1.2, Straight),
306 | make(~times=4, ~incline=-0.2, Straight),
307 | make(~times=6, ~incline=1.2, Left(ec1)),
308 | make(~times=14, ~incline=3.2, Left(ec4)),
309 | make(~times=10, ~incline=5.2, Left(ec2)),
310 | make(~times=8, ~incline=3.5, Left(ec4)),
311 | make(~times=4, ~incline=2.1, Left(ec1)),
312 | make(~times=4, ~incline=1.1, Left(ec1)),
313 | make(~times=4, ~incline=0.5, Left(ec1)),
314 | make(~times=4, Straight),
315 | makeCheckpoint(6),
316 | make(~times=4, Left(ec2)),
317 | make(~times=1, ~objects=list{makeStone(-0.9)}, Left(ec2)),
318 | make(~times=8, Left(ec2)),
319 | make(~times=1, ~incline=0.4, ~objects=list{makeStone(-0.8)}, Left(ec2)),
320 | make(~times=1, ~incline=-0.8, ~objects=list{makeStone(-0.85), makeStone(-0.65)}, Left(ec2)),
321 | make(~times=5, ~incline=0.3, Left(ec2)),
322 | make(~times=1, ~objects=list{makeStone(0.95)}, Left(ec2)),
323 | make(~times=4, Left(ec2)),
324 | make(~times=1, ~objects=list{makeStone(-0.75), makeStone(-0.5)}, Left(ec2)),
325 | make(~times=1, ~incline=-0.6, ~objects=list{makeStone(0.0), makeStone(-0.35)}, Left(ec2)),
326 | make(~times=5, ~incline=-1.2, Left(ec2)),
327 | make(~times=1, ~incline=-0.4, ~objects=list{makeStone(0.2), makeStone(0.35)}, Left(ec2)),
328 | make(~times=6, Left(ec2)),
329 | make(~times=1, ~objects=list{makeStone(0.8), makeStone(-0.35)}, Left(ec2)),
330 | make(~times=1, ~objects=list{makeStone(-0.8), makeStone(0.6), makeStone(0.9)}, Left(ec2)),
331 | make(~times=16, Left(ec2)),
332 | make(~times=4, Left(ec2)),
333 | make(~times=9, ~objects=list{makeSignRight}, Right(ec2)),
334 | make(~times=4, ~incline=1.1, Left(ec1)),
335 | make(~times=4, ~incline=0.5, Left(ec1)),
336 | } |> List.concat
337 |
338 | let make = (
339 | ~times=1,
340 | ~objects=list{},
341 | ~incline=0.,
342 | ~roadSurface=Dirt,
343 | ~groundSurface=Gravel,
344 | direction,
345 | ) => make(~times, ~objects, ~incline, ~roadSurface, ~groundSurface, direction)
346 | let track2 =
347 | list{
348 | makeStart(~groundSurface=Gravel, 29),
349 | make(~times=8, ~incline=-1.5, Straight),
350 | make(~times=10, ~incline=-1.3, Left(ec2)),
351 | make(
352 | ~times=1,
353 | ~roadSurface=Dirt,
354 | ~groundSurface=Gravel,
355 | ~incline=-1.4,
356 | ~objects=list{makeStone(0.72), makeStone(0.9)},
357 | Left(ec2),
358 | ),
359 | make(~times=6, ~incline=-1.3, Left(ec2)),
360 | make(~times=1, Left(ec1)),
361 | make(~times=22, ~incline=-2.3, Right(ec3)),
362 | make(~times=4, ~incline=-1., Straight),
363 | make(~times=4, ~incline=-0.5, Straight),
364 | make(~times=12, ~incline=-0.2, Right(hc3)),
365 | make(~times=6, Straight),
366 | make(~times=11, Left(mc1)),
367 | make(~times=1, ~objects=list{makeStone(0.8)}, Left(mc1)),
368 | make(~times=10, Left(mc1)),
369 | make(~times=4, ~incline=0.5, Straight),
370 | make(~times=4, ~incline=1.5, Straight),
371 | make(~times=4, ~incline=2.3, Straight),
372 | make(~times=4, ~incline=3.5, Straight),
373 | make(~times=10, ~incline=4.2, Straight),
374 | make(~times=1, ~objects=list{makeStone(0.5), makeStone(0.8)}, ~incline=4.7, Straight),
375 | make(~times=10, ~incline=4.9, Straight),
376 | make(~times=1, ~objects=list{makeStone(-0.9), makeStone(-0.55)}, ~incline=4.8, Straight),
377 | make(~times=4, ~incline=5.2, Straight),
378 | make(~times=2, ~incline=5.3, Straight),
379 | make(~times=4, ~incline=5.6, Straight),
380 | makeCheckpoint(~incline=5.4, ~groundSurface=Gravel, 16),
381 | make(~times=10, ~incline=5.2, ~objects=edgePosts, Straight),
382 | make(~times=6, ~incline=5.0, ~objects=edgePosts, Right(ec3)),
383 | make(~times=14, ~incline=5.4, ~objects=edgePosts, Right(mc1)),
384 | make(~times=6, ~incline=5.2, ~objects=edgePosts, Right(ec3)),
385 | make(~times=8, ~incline=4.2, ~groundSurface=Gravel, Straight),
386 | make(~times=3, ~incline=3.2, ~groundSurface=Gravel, Straight),
387 | make(~times=4, ~incline=2.2, ~objects=edgePosts, Left(ec4)),
388 | make(~times=12, ~incline=1.2, ~objects=edgePosts, Left(mc4)),
389 | make(~times=4, ~incline=1., ~objects=edgePosts, Left(ec2)),
390 | make(~times=16, ~incline=0.6, ~objects=edgePosts, Left(mc4)),
391 | make(~times=12, ~incline=0.2, ~objects=edgePosts, Right(hc1)),
392 | make(~times=4, ~incline=-0.2, ~objects=edgePosts, Right(ec2)),
393 | make(~times=4, ~incline=-0.4, ~objects=edgePosts, Straight),
394 | make(~times=4, ~incline=-0.2, Straight),
395 | make(~times=8, Straight),
396 | make(~times=1, ~objects=list{makeStone(-0.9)}, Straight),
397 | make(~times=1, ~incline=-0.3, ~objects=list{makeStone(-0.7)}, Straight),
398 | make(~times=1, ~incline=-0.4, ~objects=list{makeStone(-0.5)}, Straight),
399 | make(~times=1, ~incline=-0.4, ~objects=list{makeStone(-0.8), makeStone(-0.7)}, Straight),
400 | make(~times=1, ~incline=-0.4, ~objects=list{makeStone(-0.3)}, Straight),
401 | make(~times=1, ~incline=-0.4, ~objects=list{makeStone(-0.), makeStone(0.9)}, Straight),
402 | make(~times=1, ~incline=-0.4, ~objects=list{makeStone(0.3), makeStone(-0.7)}, Straight),
403 | make(~times=4, ~incline=-0.6, Straight),
404 | make(~times=12, ~incline=-1.2, Straight),
405 | make(~times=4, ~incline=-0.6, Straight),
406 | make(~times=4, ~incline=-0.2, Straight),
407 | make(~times=6, Straight),
408 | make(~times=4, ~incline=0.6, Straight),
409 | make(~times=6, ~incline=1.6, Straight),
410 | make(~times=4, ~incline=3.1, Right(hc1)),
411 | make(~times=12, ~incline=4.6, Right(hc2)),
412 | make(~times=8, ~incline=3.6, Right(mc2)),
413 | make(~times=4, ~incline=2.6, Straight),
414 | make(~times=4, ~incline=1., Straight),
415 | make(~times=4, ~incline=0.2, Straight),
416 | make(~times=4, Straight),
417 | make(~times=8, ~incline=-0.6, Straight),
418 | make(~times=8, ~incline=-1.6, Straight),
419 | make(~times=8, ~incline=-0.6, Straight),
420 | make(~times=4, Straight),
421 | make(~times=8, Left(ec4)),
422 | make(~times=6, ~incline=1., Left(ec1)),
423 | make(~times=6, ~incline=0.2, Straight),
424 | make(~times=12, ~incline=0.8, Right(ec4)),
425 | make(~times=14, ~incline=2.2, ~objects=list{makeSignRight}, Right(mc3)),
426 | make(~times=6, ~incline=3.4, Right(ec3)),
427 | make(~times=2, ~incline=4.2, Straight),
428 | make(~times=8, ~incline=5.2, Straight),
429 | make(~times=6, ~incline=6.1, Straight),
430 | make(~times=8, ~incline=5.8, ~objects=edgePosts, Left(mc1)),
431 | make(~times=14, ~incline=6.5, ~objects=edgePosts, Left(hc1)),
432 | make(~times=8, ~incline=7.5, ~objects=list{makeSignLeft}, Left(mc3)),
433 | make(~times=4, ~incline=7.8, ~objects=list{makeSignLeft}, Left(ec2)),
434 | make(~times=2, ~incline=8.8, Straight),
435 | makeCheckpoint(~incline=9.2, ~groundSurface=Gravel, 18),
436 | make(~times=12, ~incline=9.9, Left(ec4)),
437 | make(~times=2, ~incline=10.1, Straight),
438 | make(~times=16, ~incline=10.9, Right(mc1)),
439 | make(~times=10, ~incline=12.4, ~objects=list{makeSignRight}, Right(hc2)),
440 | make(~times=10, ~incline=11.4, Right(ec2)),
441 | make(~times=4, ~incline=9.4, Right(mc2)),
442 | make(~times=8, ~incline=8.4, Left(ec1)),
443 | make(~times=12, ~incline=6.2, Straight),
444 | make(~times=6, ~incline=4.5, Left(ec3)),
445 | make(~times=18, ~incline=4.2, Left(mc3)),
446 | make(~times=24, ~incline=4.3, Left(hc1)),
447 | make(~times=28, ~incline=4.1, ~objects=list{makeSignLeft}, Left(hc3)),
448 | make(~times=12, ~incline=4.0, Right(mc1)),
449 | make(~times=12, ~incline=3.0, Right(ec4)),
450 | make(~times=12, ~incline=2.0, Straight),
451 | make(~times=1, ~incline=1.8, ~objects=list{makeStone(0.8)}, Straight),
452 | make(~times=1, ~incline=1.5, ~objects=list{makeStone(0.6), makeStone(0.9)}, Straight),
453 | make(~times=6, ~incline=0.1, Right(ec4)),
454 | make(~times=1, ~incline=0.3, ~objects=list{makeStone(-0.8)}, Right(ec4)),
455 | make(~times=1, ~incline=0.6, ~objects=list{makeStone(-0.4)}, Right(ec4)),
456 | make(~times=12, ~incline=0.8, Right(ec4)),
457 | make(~times=4, ~incline=0.6, ~objects=list{makeSignRight},Right(hp1)),
458 | make(~times=18, ~incline=0.4, Right(mc2)),
459 | make(~times=6, ~incline=0.2, Right(mc1)),
460 | make(~times=1, ~incline=0.3, ~objects=list{makeStone(0.)}, Straight),
461 | makeCheckpoint(~incline=0.4, ~groundSurface=Gravel, 9),
462 | make(~times=8, ~incline=0., Straight),
463 | make(~times=1, ~incline=-1.2, ~objects=list{makeStone(-0.8)}, Straight),
464 | make(~times=1, ~incline=-1.2, ~objects=list{makeStone(-0.6), makeStone(-0.9)}, Straight),
465 | make(~times=12, ~incline=0., Straight),
466 | make(~times=1, ~incline=-1.2, ~objects=list{makeStone(0.)}, Straight),
467 | make(~times=1, ~incline=-1.2, ~objects=list{makeStone(-0.2), makeStone(0.2)}, Straight),
468 | make(~times=20, ~incline=0., ~objects=edgePosts, Right(mc3)),
469 | makeCheckpoint(~incline=1.2, ~groundSurface=Gravel, 9),
470 | make(~times=2, ~incline=0.5, Right(ec1)),
471 | make(~times=8, ~incline=1.1, Right(ec2)),
472 | make(~times=4, ~incline=0.6, Right(ec3)),
473 | make(~times=4, ~incline=0.1, Right(ec4)),
474 | make(~times=16, ~incline=-0.6, Right(mc2)),
475 | make(~times=8, ~incline=-0.2, Straight),
476 | make(~times=1, ~incline=-0., ~objects=list{makeStone(-0.8), makeStone(-0.5), makeStone(-0.1), makeStone(0.2)}, Straight),
477 | make(~times=7, ~incline=-0., Straight),
478 | make(~times=1, ~incline=-0., ~objects=list{makeStone(0.8), makeStone(0.5), makeStone(0.2)}, Straight),
479 | make(~times=1, ~incline=-0., ~objects=list{makeStone(-0.1), makeStone(-0.7)}, Straight),
480 | makeCheckpoint(~incline=0.2, ~groundSurface=Gravel, 9),
481 | make(~times=1, ~incline=0.5, ~objects=list{makeStone(0.8)}, Straight),
482 | make(~times=8, ~incline=1., Straight),
483 | make(~times=8, ~incline=0., Left(mc2)),
484 | make(~times=16, ~incline=0., Left(mc4)),
485 | make(~times=8, ~incline=0., Left(mc1)),
486 | make(~times=16, ~incline=0., Left(hc1)),
487 | make(~times=4, ~incline=0., Left(ec3)),
488 | make(~times=1, ~incline=-0., ~objects=list{makeStone(-0.1), makeStone(-0.7)}, Straight),
489 | make(~times=1, ~incline=-0., ~objects=list{makeStone(-0.5), makeStone(-1.1)}, Straight),
490 | make(~times=16, ~incline=0.3, Right(mc1)),
491 | make(~times=16, ~incline=-0.3, Right(mc2)),
492 | make(~times=16, ~incline=0.2, Right(mc1)),
493 | make(~times=1, ~incline=-0., ~objects=list{makeStone(-0.1), makeStone(-0.7)}, Straight),
494 | make(~times=1, ~incline=-0., ~objects=list{makeStone(-0.5), makeStone(-1.1)}, Straight),
495 | make(~times=12, Left(mc1)),
496 | make(~times=1, ~objects=list{makeStone(-0.8), makeStone(-0.5), makeStone(-0.2), makeStone(0.15)}, Left(mc1)),
497 | make(~times=1, ~objects=list{makeStone(-0.7), makeStone(0.25)}, Left(mc1)),
498 | make(~times=12, Left(mc2)),
499 | make(~times=24, Left(ec3)),
500 | make(~times=1, ~objects=list{makeStone(0.8), makeStone(0.5), makeStone(0.15), makeStone(-0.15)}, Left(mc1)),
501 | make(~times=1, ~objects=list{makeStone(0.7), makeStone(-0.25)}, Left(mc1)),
502 | make(~times=8, ~incline=1., Straight),
503 | makeCheckpoint(~incline=0.6, ~groundSurface=Gravel, 9),
504 | make(~times=16, ~incline=-0.3, Right(mc2)),
505 | make(~times=1, ~incline=-0.6, ~objects=list{makeStone(-1.1)}, Right(mc1)),
506 | make(~times=1, ~incline=-1.2, ~objects=list{makeStone(0.)}, Right(mc1)),
507 | make(~times=12, ~incline=-2.2, Right(mc2)),
508 | make(~times=18, ~incline=-2.4, Right(hc1)),
509 | make(~times=12, ~incline=-1.5, Right(mc3)),
510 | make(~times=12, ~incline=-1.2, Left(mc1)),
511 | make(~times=24, ~incline=-0.5, Left(mc4)),
512 | make(~times=12, ~incline=-0.2, Left(mc2)),
513 | make(~times=12, ~incline=0., Straight),
514 | make(~times=1, ~incline=0.6, ~objects=list{makeStone(0.9)}, Straight),
515 | make(~times=1, ~incline=0.6, ~objects=list{makeStone(0.7)}, Straight),
516 | make(~times=4, ~incline=0., Straight),
517 | make(~times=8, ~incline=1.0, Straight),
518 | makeCheckpoint(~incline=0.6, ~groundSurface=Gravel, 9),
519 | make(~times=1, ~incline=0.4, ~objects=list{makeStone(0.9)}, ~groundSurface=Gravel, Straight),
520 | make(~times=4, ~incline=0., Straight),
521 | make(~times=12, ~incline=-2., Straight),
522 | make(~times=12, ~incline=-2., Left(ec4)),
523 | make(~times=12, ~incline=-2., Left(mc2)),
524 | make(~times=8, ~incline=-2., Left(hc2)),
525 | make(~times=8, ~incline=-2., Left(hc4)),
526 | make(~times=8, ~incline=-1.5, Left(hc1)),
527 | make(~times=8, ~incline=-1., Left(mc1)),
528 | make(~times=4, ~incline=-0.5, Straight),
529 | make(~times=4, ~incline=-0.2, Straight),
530 | make(~times=1, ~objects=list{makeStone(0.9)}, Straight),
531 | make(~times=1, ~objects=list{makeStone(0.7)}, Straight),
532 | make(~times=12, Straight),
533 | make(~times=1, ~objects=list{makeStone(0.9), makeStone(0.7), makeStone(0.3), makeStone(-0.8)}, Straight),
534 | make(~times=1, ~objects=list{makeStone(0.5)}, Straight),
535 | make(~times=12, Straight),
536 | make(~times=1, ~objects=list{makeStone(0.2), makeStone(-0.3), makeStone(0.3), makeStone(-0.8)}, Straight),
537 | make(~times=1, ~objects=list{makeStone(0.4), makeStone(-0.5), makeStone(0.6), makeStone(-0.2)}, Straight),
538 | make(~times=2, Straight),
539 | } |> List.concat
540 |
541 | let make = (
542 | ~times=1,
543 | ~objects=list{},
544 | ~incline=0.,
545 | ~roadSurface=Dirt,
546 | ~groundSurface=Grass,
547 | direction,
548 | ) => make(~times, ~objects, ~incline, ~roadSurface, ~groundSurface, direction)
549 | let track3 =
550 | list{
551 | makeStart(~groundSurface=Grass, 29),
552 | make(~times=8, ~incline=-1.5, Straight),
553 | make(~times=8, ~incline=-2.5, Straight),
554 | make(~times=8, ~incline=-3.5, Straight),
555 | make(~times=8, ~incline=-3.2, Straight),
556 | make(~times=16, ~incline=-1.5, Straight),
557 | make(~times=16, ~incline=-0.6, Straight),
558 | make(~times=8, ~incline=-0.3, Left(mc2)),
559 | make(~times=24, ~incline=-0.4, Left(mc4)),
560 | make(~times=8, ~incline=-0.6, Left(mc4)),
561 | make(~times=8, ~incline=-0.0, Left(ec3)),
562 | make(~times=16, ~incline=0.2, Straight),
563 | make(~times=8, ~incline=-0.1, Straight),
564 | make(~times=16, ~incline=-1.1, Right(hc1)),
565 | make(~times=16, ~incline=-1.6, Left(hc1)),
566 | make(~times=16, ~incline=-1.9, Right(hc1)),
567 | make(~times=16, ~incline=-0.9, Right(ec3)),
568 | make(~times=16, ~incline=0., Straight),
569 | makeCheckpoint(~incline=0.6, 6),
570 | make(~times=16, ~incline=0., Straight),
571 | make(~times=16, ~incline=0.1, Right(mc3)),
572 | make(~times=8, ~incline=-0.3, Left(mc3)),
573 | make(~times=24, ~incline=-0.6, Left(hc2)),
574 | make(~times=8, ~incline=-0.2, Left(mc2)),
575 | make(~times=7, ~incline=0., ~groundSurface=Water, Straight),
576 | makeCheckpoint(~incline=0.6, ~groundSurface=Water, 9),
577 | make(~times=8, ~incline=0., ~groundSurface=Water, Straight),
578 | make(~times=2, ~incline=0.4, Straight),
579 | make(~times=2, ~incline=1.4, Straight),
580 | make(~times=16, ~incline=3.4, Straight),
581 | make(~times=24, ~incline=3.1, Right(hc3)),
582 | make(~times=12, ~incline=2.4, Right(mc2)),
583 | make(~times=12, ~incline=1., Right(ec2)),
584 | make(~times=24, ~incline=0.3, Left(ec4)),
585 | make(~times=8, ~incline=0., Straight),
586 | }
587 | |> List.concat;
588 |
589 | track->List.append(track2)->List.append(track3)
590 | }
591 |
592 | Random.init(69)
593 | let roll = ref(Random.int(9) + 1)
594 | let reroll = () => roll.contents = Random.int(9) + 1
595 | let positions = [-1.9, -1.8, -1.7, -1.6, -1.5, 1.5, 1.6, 1.7, 1.8, 1.9]
596 | let track = demoTrack |> List.mapi((i, road) => {
597 | reroll()
598 | let t = mod(i, 10)
599 | roll.contents >= t
600 | ? {
601 | reroll()
602 | if (road.groundSurface!=Water) {
603 | {
604 | ...road,
605 | objects: road.objects |> List.append(list{
606 | Object.Prefabs.makeTree(positions[roll.contents - 1]),
607 | }),
608 | }
609 | } else {
610 | road
611 | }
612 |
613 | }
614 | : road
615 | })
616 |
617 | let init = {track: track}
618 |
619 | let isCheckpoint = t =>
620 | switch t.direction {
621 | | Checkpoint(_) => true
622 | | _ => false
623 | }
624 |
625 | let lastTrack = ref(track)
626 | let progress = state =>
627 | List.length(state.track) > 106
628 | ? {track: List.tl(state.track)}
629 | : {
630 | lastTrack :=
631 | lastTrack.contents->List.rev |> List.map(t => {...t, incline: t.incline *. 1.1})
632 | {track: List.tl(List.append(state.track, lastTrack.contents))}
633 | }
634 |
635 | let head = state => List.hd(state.track)
636 | let tail = state => List.tl(state.track)
637 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@bsansouci/reasongl-web@github:RawToast/reasongl-web":
6 | version "1.0.1"
7 | resolved "https://codeload.github.com/RawToast/reasongl-web/tar.gz/fde813f9af0338b17a665b41d13418c9f7d09076"
8 | dependencies:
9 | gl-matrix "*"
10 |
11 | "@esbuild/aix-ppc64@0.19.12":
12 | version "0.19.12"
13 | resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f"
14 | integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==
15 |
16 | "@esbuild/android-arm64@0.19.12":
17 | version "0.19.12"
18 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4"
19 | integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==
20 |
21 | "@esbuild/android-arm@0.19.12":
22 | version "0.19.12"
23 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824"
24 | integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==
25 |
26 | "@esbuild/android-x64@0.19.12":
27 | version "0.19.12"
28 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d"
29 | integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==
30 |
31 | "@esbuild/darwin-arm64@0.19.12":
32 | version "0.19.12"
33 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e"
34 | integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==
35 |
36 | "@esbuild/darwin-x64@0.19.12":
37 | version "0.19.12"
38 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd"
39 | integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==
40 |
41 | "@esbuild/freebsd-arm64@0.19.12":
42 | version "0.19.12"
43 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487"
44 | integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==
45 |
46 | "@esbuild/freebsd-x64@0.19.12":
47 | version "0.19.12"
48 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c"
49 | integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==
50 |
51 | "@esbuild/linux-arm64@0.19.12":
52 | version "0.19.12"
53 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b"
54 | integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==
55 |
56 | "@esbuild/linux-arm@0.19.12":
57 | version "0.19.12"
58 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef"
59 | integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==
60 |
61 | "@esbuild/linux-ia32@0.19.12":
62 | version "0.19.12"
63 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601"
64 | integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==
65 |
66 | "@esbuild/linux-loong64@0.19.12":
67 | version "0.19.12"
68 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299"
69 | integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==
70 |
71 | "@esbuild/linux-mips64el@0.19.12":
72 | version "0.19.12"
73 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec"
74 | integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==
75 |
76 | "@esbuild/linux-ppc64@0.19.12":
77 | version "0.19.12"
78 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8"
79 | integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==
80 |
81 | "@esbuild/linux-riscv64@0.19.12":
82 | version "0.19.12"
83 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf"
84 | integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==
85 |
86 | "@esbuild/linux-s390x@0.19.12":
87 | version "0.19.12"
88 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8"
89 | integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==
90 |
91 | "@esbuild/linux-x64@0.19.12":
92 | version "0.19.12"
93 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78"
94 | integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==
95 |
96 | "@esbuild/netbsd-x64@0.19.12":
97 | version "0.19.12"
98 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b"
99 | integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==
100 |
101 | "@esbuild/openbsd-x64@0.19.12":
102 | version "0.19.12"
103 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0"
104 | integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==
105 |
106 | "@esbuild/sunos-x64@0.19.12":
107 | version "0.19.12"
108 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30"
109 | integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==
110 |
111 | "@esbuild/win32-arm64@0.19.12":
112 | version "0.19.12"
113 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae"
114 | integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==
115 |
116 | "@esbuild/win32-ia32@0.19.12":
117 | version "0.19.12"
118 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67"
119 | integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==
120 |
121 | "@esbuild/win32-x64@0.19.12":
122 | version "0.19.12"
123 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae"
124 | integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==
125 |
126 | "@rollup/rollup-android-arm-eabi@4.13.0":
127 | version "4.13.0"
128 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz#b98786c1304b4ff8db3a873180b778649b5dff2b"
129 | integrity sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==
130 |
131 | "@rollup/rollup-android-arm64@4.13.0":
132 | version "4.13.0"
133 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz#8833679af11172b1bf1ab7cb3bad84df4caf0c9e"
134 | integrity sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==
135 |
136 | "@rollup/rollup-darwin-arm64@4.13.0":
137 | version "4.13.0"
138 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz#ef02d73e0a95d406e0eb4fd61a53d5d17775659b"
139 | integrity sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==
140 |
141 | "@rollup/rollup-darwin-x64@4.13.0":
142 | version "4.13.0"
143 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz#3ce5b9bcf92b3341a5c1c58a3e6bcce0ea9e7455"
144 | integrity sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==
145 |
146 | "@rollup/rollup-linux-arm-gnueabihf@4.13.0":
147 | version "4.13.0"
148 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz#3d3d2c018bdd8e037c6bfedd52acfff1c97e4be4"
149 | integrity sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==
150 |
151 | "@rollup/rollup-linux-arm64-gnu@4.13.0":
152 | version "4.13.0"
153 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz#5fc8cc978ff396eaa136d7bfe05b5b9138064143"
154 | integrity sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==
155 |
156 | "@rollup/rollup-linux-arm64-musl@4.13.0":
157 | version "4.13.0"
158 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz#f2ae7d7bed416ffa26d6b948ac5772b520700eef"
159 | integrity sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==
160 |
161 | "@rollup/rollup-linux-riscv64-gnu@4.13.0":
162 | version "4.13.0"
163 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz#303d57a328ee9a50c85385936f31cf62306d30b6"
164 | integrity sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==
165 |
166 | "@rollup/rollup-linux-x64-gnu@4.13.0":
167 | version "4.13.0"
168 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz#f672f6508f090fc73f08ba40ff76c20b57424778"
169 | integrity sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==
170 |
171 | "@rollup/rollup-linux-x64-musl@4.13.0":
172 | version "4.13.0"
173 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz#d2f34b1b157f3e7f13925bca3288192a66755a89"
174 | integrity sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==
175 |
176 | "@rollup/rollup-win32-arm64-msvc@4.13.0":
177 | version "4.13.0"
178 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz#8ffecc980ae4d9899eb2f9c4ae471a8d58d2da6b"
179 | integrity sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==
180 |
181 | "@rollup/rollup-win32-ia32-msvc@4.13.0":
182 | version "4.13.0"
183 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz#a7505884f415662e088365b9218b2b03a88fc6f2"
184 | integrity sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==
185 |
186 | "@rollup/rollup-win32-x64-msvc@4.13.0":
187 | version "4.13.0"
188 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz#6abd79db7ff8d01a58865ba20a63cfd23d9e2a10"
189 | integrity sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==
190 |
191 | "@types/estree@1.0.5":
192 | version "1.0.5"
193 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
194 | integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
195 |
196 | balanced-match@^1.0.0:
197 | version "1.0.2"
198 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
199 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
200 |
201 | brace-expansion@^1.1.7:
202 | version "1.1.11"
203 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
204 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
205 | dependencies:
206 | balanced-match "^1.0.0"
207 | concat-map "0.0.1"
208 |
209 | concat-map@0.0.1:
210 | version "0.0.1"
211 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
212 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
213 |
214 | esbuild@^0.19.3:
215 | version "0.19.12"
216 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04"
217 | integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==
218 | optionalDependencies:
219 | "@esbuild/aix-ppc64" "0.19.12"
220 | "@esbuild/android-arm" "0.19.12"
221 | "@esbuild/android-arm64" "0.19.12"
222 | "@esbuild/android-x64" "0.19.12"
223 | "@esbuild/darwin-arm64" "0.19.12"
224 | "@esbuild/darwin-x64" "0.19.12"
225 | "@esbuild/freebsd-arm64" "0.19.12"
226 | "@esbuild/freebsd-x64" "0.19.12"
227 | "@esbuild/linux-arm" "0.19.12"
228 | "@esbuild/linux-arm64" "0.19.12"
229 | "@esbuild/linux-ia32" "0.19.12"
230 | "@esbuild/linux-loong64" "0.19.12"
231 | "@esbuild/linux-mips64el" "0.19.12"
232 | "@esbuild/linux-ppc64" "0.19.12"
233 | "@esbuild/linux-riscv64" "0.19.12"
234 | "@esbuild/linux-s390x" "0.19.12"
235 | "@esbuild/linux-x64" "0.19.12"
236 | "@esbuild/netbsd-x64" "0.19.12"
237 | "@esbuild/openbsd-x64" "0.19.12"
238 | "@esbuild/sunos-x64" "0.19.12"
239 | "@esbuild/win32-arm64" "0.19.12"
240 | "@esbuild/win32-ia32" "0.19.12"
241 | "@esbuild/win32-x64" "0.19.12"
242 |
243 | fs.realpath@^1.0.0:
244 | version "1.0.0"
245 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
246 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
247 |
248 | fsevents@~2.3.2, fsevents@~2.3.3:
249 | version "2.3.3"
250 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
251 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
252 |
253 | gl-matrix@*:
254 | version "3.4.3"
255 | resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9"
256 | integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==
257 |
258 | glob@^7.1.3:
259 | version "7.2.3"
260 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
261 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
262 | dependencies:
263 | fs.realpath "^1.0.0"
264 | inflight "^1.0.4"
265 | inherits "2"
266 | minimatch "^3.1.1"
267 | once "^1.3.0"
268 | path-is-absolute "^1.0.0"
269 |
270 | inflight@^1.0.4:
271 | version "1.0.6"
272 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
273 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
274 | dependencies:
275 | once "^1.3.0"
276 | wrappy "1"
277 |
278 | inherits@2:
279 | version "2.0.4"
280 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
281 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
282 |
283 | minimatch@^3.1.1:
284 | version "3.1.2"
285 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
286 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
287 | dependencies:
288 | brace-expansion "^1.1.7"
289 |
290 | nanoid@^3.3.7:
291 | version "3.3.7"
292 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
293 | integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
294 |
295 | once@^1.3.0:
296 | version "1.4.0"
297 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
298 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
299 | dependencies:
300 | wrappy "1"
301 |
302 | path-is-absolute@^1.0.0:
303 | version "1.0.1"
304 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
305 | integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
306 |
307 | picocolors@^1.0.0:
308 | version "1.0.0"
309 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
310 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
311 |
312 | postcss@^8.4.35:
313 | version "8.4.36"
314 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.36.tgz#dba513c3c3733c44e0288a712894f8910bbaabc6"
315 | integrity sha512-/n7eumA6ZjFHAsbX30yhHup/IMkOmlmvtEi7P+6RMYf+bGJSUHc3geH4a0NSZxAz/RJfiS9tooCTs9LAVYUZKw==
316 | dependencies:
317 | nanoid "^3.3.7"
318 | picocolors "^1.0.0"
319 | source-map-js "^1.1.0"
320 |
321 | "reprocessing@github:RawToast/reprocessing#ml":
322 | version "1.0.0"
323 | resolved "https://codeload.github.com/RawToast/reprocessing/tar.gz/b094e495865d20e4728fe25b4abf0b0c52b14e85"
324 | dependencies:
325 | "@bsansouci/reasongl-web" "github:RawToast/reasongl-web"
326 |
327 | rescript@^10.1.3:
328 | version "10.1.4"
329 | resolved "https://registry.yarnpkg.com/rescript/-/rescript-10.1.4.tgz#0f37710d371f32a704f17b4e804f66ce3c79a305"
330 | integrity sha512-FFKlS9AG/XrLepWsyw7B+A9DtQBPWEPDPDKghV831Y2KGbie+eeFBOS0xtRHp0xbt7S0N2Dm6hhX+kTZQ/3Ybg==
331 |
332 | rimraf@^3.0.0:
333 | version "3.0.2"
334 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
335 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
336 | dependencies:
337 | glob "^7.1.3"
338 |
339 | rollup@^4.2.0:
340 | version "4.13.0"
341 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.0.tgz#dd2ae144b4cdc2ea25420477f68d4937a721237a"
342 | integrity sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==
343 | dependencies:
344 | "@types/estree" "1.0.5"
345 | optionalDependencies:
346 | "@rollup/rollup-android-arm-eabi" "4.13.0"
347 | "@rollup/rollup-android-arm64" "4.13.0"
348 | "@rollup/rollup-darwin-arm64" "4.13.0"
349 | "@rollup/rollup-darwin-x64" "4.13.0"
350 | "@rollup/rollup-linux-arm-gnueabihf" "4.13.0"
351 | "@rollup/rollup-linux-arm64-gnu" "4.13.0"
352 | "@rollup/rollup-linux-arm64-musl" "4.13.0"
353 | "@rollup/rollup-linux-riscv64-gnu" "4.13.0"
354 | "@rollup/rollup-linux-x64-gnu" "4.13.0"
355 | "@rollup/rollup-linux-x64-musl" "4.13.0"
356 | "@rollup/rollup-win32-arm64-msvc" "4.13.0"
357 | "@rollup/rollup-win32-ia32-msvc" "4.13.0"
358 | "@rollup/rollup-win32-x64-msvc" "4.13.0"
359 | fsevents "~2.3.2"
360 |
361 | source-map-js@^1.1.0:
362 | version "1.1.0"
363 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.1.0.tgz#9e7d5cb46f0689fb6691b30f226937558d0fa94b"
364 | integrity sha512-9vC2SfsJzlej6MAaMPLu8HiBSHGdRAJ9hVFYN1ibZoNkeanmDmLUcIrj6G9DGL7XMJ54AKg/G75akXl1/izTOw==
365 |
366 | vite@^5.1.6:
367 | version "5.1.6"
368 | resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.6.tgz#706dae5fab9e97f57578469eef1405fc483943e4"
369 | integrity sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==
370 | dependencies:
371 | esbuild "^0.19.3"
372 | postcss "^8.4.35"
373 | rollup "^4.2.0"
374 | optionalDependencies:
375 | fsevents "~2.3.3"
376 |
377 | wrappy@1:
378 | version "1.0.2"
379 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
380 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
381 |
--------------------------------------------------------------------------------