How to program 3D cars and bikes (Race and Motocross)
Inside the 3D Race and Motocross examples: vehicle physics, chase camera, path points (those number lists), rival autopilot, laps and the mountain.
1. The player BECOMES the vehicle
In both games you don't control a walking sprite: the player drive block swaps the 3D World player for a car or a bike.
β’ evt_bandeira β’ m3d_jog_veiculo [VEIC: carro, COR: #3B6FD8] β’ m3d_camera [MODO: perseguicao] β’ m3d_jog_vel [VEL: 4.3] β’ m3d_controles [MODO: sim]
Inside, the vehicle keeps a speed (forward velocity) and, every frame (60 times a second):
- W adds acceleration; S brakes (and, when stopped, reverses); with no key, friction slowly stops the car. That's the feeling of inertia.
- A/D turn the direction, but turning is proportional to speed: a stopped car doesn't turn (like a real car).
- Speed becomes a step forward: x changes by sine(direction) Γ speed and z by βcosine(direction) Γ speed.
- On a 1-block step the vehicle climbs; on a wall it loses speed and fires when the player's vehicle crashes.
- The bike accelerates more, turns faster and jumps with Space; it leans in turns and its wheels spin with the speed.
The chase camera stays behind the vehicle and turns with a delay (it "chases" the car's direction), so turns look smooth.
2. The rivals: what are those numbers?
In a rival you will see a list like this:
36, 41, 46.1, 51.1, 56.2, 61.2, 66.3, 71.3, 76.4, 81.6, 86.6, 91, 94.3, 96.4, 97, 96.1, 93.9, 90.3, 85.9, 80.8, 75.6, 70.5, 65.5, 60.4, 55.4, 50.3, 45.3, 40.2, 35.2, 30.1, 25, 19.8, 15.1, 11.2, 8.5, 7.1, 7.3, 8.8, 11.8, 15.8, 20.6, 25.9, 31
They are the x coordinates of the path points (waypoints) of the green rival. A second list, path Z, has the z coordinates. The 1st number of each list is point 1, the 2nd of each is point 2, and so on: 43 points around the track, like breadcrumbs.
Read the list and you'll see the track in it:
- 36 β 91 goes up by 5: the top straight, the car moving right (x growing).
- 94.3 β 97 β 85.9 grows slowly, reaches 97 (the rightmost point) and comes back: the right turn (a half circle). In the turn x changes little, because the car moves more in z.
- 80.8 β 15.1 goes down by 5: the bottom straight, going back left.
- 11.2 β 7.1 β 31: the left turn (7.1 is the leftmost point) and back near the start.
Where did they come from? The track is a "stadium" oval: two 52-block straights and two half circles with radius 18 (about 217 blocks around). The program walked along it and wrote down a point every ~5 blocks (217 Γ· 5 β 43). On straights it just adds; in turns it uses cosine and sine (x = center + radius Γ cos(angle)). Each rival drives in a different lane (a bit inside or outside), so the three lists are similar but not equal. The lists are stored as comma-separated text and the split text by "," block turns the text into a list.
3. The autopilot (the rival's blocks)
β’ evt_bandeira
β’ m3d_corpo [FORMA: carro, COR: #3E9E3A, TAM: 100]
β’ m3d_corpo_fisica [MODO: sim]
β’ var_definir [VAR: caminhoX, VALOR: (arr_dividir)]
β’ var_definir [VAR: caminhoZ, VALOR: (arr_dividir)]
β’ var_definir [VAR: ponto, VALOR: 1]
β’ evt_receber
β’ ctl_repetir_ate [COND: (op_maior)]
β’ m3d_corpo_dirigir [X: (arr_item), Z: (arr_item), VEL: 12]
β’ ctl_se [COND: (op_menor)]
β’ var_adicionar [VAR: ponto, VALOR: 1]
β’ ctl_se [COND: (op_maior)]
β’ var_definir [VAR: ponto, VALOR: 1]
β’ var_adicionar [VAR: voltas, VALOR: 1]- drive to x z at speed turns the car a little towards the current point (like a steering wheel) and moves. It doesn't teleport, so it makes nice turns.
- When my distance to x z is under 3.5 blocks, the rival arrived and goes to the next point (point + 1).
- Past the last point? Back to point 1 and add a lap.
- After 3 laps it adds 1 to "rivals finished". When you cross the line, your position is "rivals finished + 1".
Different speeds (12 / 12.6 / 13.2) give the rivals different levels. Want a harder rival? Raise its speed.
4. Make your own track and record the path by driving
No math needed! Drive the car around your track and let a script write down the points every half second:
β’ evt_tecla [TECLA: g] β’ var_definir [VAR: caminhoX, VALOR: (arr_vazia)] β’ var_definir [VAR: caminhoZ, VALOR: (arr_vazia)] β’ ctl_repetir [VEZES: 60] β’ arr_adicionar [VALOR: (m3d_jog_pos), VAR: caminhoX] β’ arr_adicionar [VALOR: (m3d_jog_pos), VAR: caminhoZ] β’ ctl_esperar [SEG: 0.5]
Then show the caminhoX and caminhoZ variables on the stage (or use "say") and use those numbers in the rivals.
5. Laps, grass and crashes (your car)
- Counting laps without cheating: a lap only counts if you passed the middle of the track (bottom straight) and then the checkered line. So you can't go back and forth over the line.
- Grass slows you down: the game checks the block under the car (y β 0.5). If it's grass, speed drops.
β’ ctl_sempre
β’ ctl_se_senao [COND: (op_igual)]
β’ m3d_jog_vel [VEL: 2.4]
β¦:
β’ m3d_jog_vel [VEL: 4.3]- Time and best lap use the timer block (Sensing), which is precise. Waiting 0.1 s and adding 0.1 runs late, because each repeat takes a bit longer.
6. The bike and the mountain
The mountain was built by code: the trail climbs from left to right and its height is about 8 + x Γ 0.2 (1 block up every 5). The program makes sure the trail never climbs more than 1 block from one column to the next, otherwise the bike would get stuck. On one side there is a rock wall (so you stay on the trail) and on the other the cliff.
β’ evt_bandeira
β’ m3d_jog_veiculo [VEIC: moto, COR: #FF8C1A]
β’ m3d_camera [MODO: perseguicao]
β’ ctl_sempre
β’ ctl_se [COND: (op_menor)]
β’ m3d_jog_inicio
β’ ctl_se [COND: (op_maior)]
β’ m3d_jog_marcar- Fell? If the bike is well below the trail (less than 4 + x Γ 0.2), it goes back to the last checkpoint.
- Checkpoint: past the yellow post (x greater than 41), set start point where the player is saves the new start there.
- Side camera: press C. The camera sees the mountain in profile, like hill-climb games.
7. Challenges
- Make a figure-8 track and record the rivals' path by driving (section 4).
- Create a turbo: when pressing Shift, "player speed 6" for 2 seconds.
- In motocross, add a "ghost" rival that follows the trail points.
- Switch the camera to top-down and make a remote-control car game.