Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "raylib.h"
- #include "raymath.h"
- #include <stdio.h>
- #include <math.h>
- // RayGUI implementation
- #define RAYGUI_IMPLEMENTATION
- #include "raygui.h"
- #ifndef MAP_DIFFUSE
- #define MAP_DIFFUSE MATERIAL_MAP_ALBEDO
- #endif
- #define MAX_PLANES 4
- int main(void)
- {
- // Initialize window (can be resized)
- InitWindow(1920, 1080, "Airplane Simulation");
- SetTargetFPS(60);
- // --- Load terrain ---
- Image hm = LoadImage("Great Lakes/Height-Map.png");
- if (!hm.data) { printf("Failed to load heightmap\n"); CloseWindow(); return 1; }
- ImageResize(&hm, hm.width/3, hm.height/3);
- Mesh terrainMesh = GenMeshHeightmap(hm, (Vector3){1000,350,1000});
- Model terrain = LoadModelFromMesh(terrainMesh);
- UnloadImage(hm);
- Texture2D terrainTex = LoadTexture("Great Lakes/Diffuse-Map.png");
- terrain.materials[0].maps[MAP_DIFFUSE].texture = terrainTex;
- // Optional saturation shader
- Shader sat = LoadShader(0, "Assets/saturation.fs");
- float satVal = 3.0f;
- SetShaderValue(sat, GetShaderLocation(sat, "saturation"), &satVal, SHADER_UNIFORM_FLOAT);
- terrain.materials[0].shader = sat;
- // --- Load plane model ---
- Model planeModel = LoadModel("Assets/plane.obj");
- Texture2D planeTex = LoadTexture("Assets/An2_aeroflot.png");
- planeModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = planeTex;
- // --- Load runway ---
- Texture2D runwayTex = LoadTexture("Assets/runway_texture.png");
- Mesh runwayMesh = GenMeshPlane(6.0f, 22.0f, 1, 1);
- Model runway = LoadModelFromMesh(runwayMesh);
- runway.materials[0].maps[MAP_DIFFUSE].texture = runwayTex;
- // --- Audio ---
- InitAudioDevice();
- Music engineSound = LoadMusicStream("Assets/airplane-sound.mp3");
- PlayMusicStream(engineSound);
- // --- Spawn setup ---
- const float spawnX = -1000.0f, spawnY = 5500.0f, spawnZ = 19000.0f;
- Matrix scaleM = MatrixScale(0.005f, 0.005f, 0.005f);
- Matrix corrM = MatrixRotateY(PI/2);
- Matrix baseSpawn = MatrixMultiply(
- MatrixTranslate(spawnX, spawnY, spawnZ),
- MatrixMultiply(corrM, scaleM)
- );
- Matrix spawned[MAX_PLANES] = { 0 };
- int spawnedCount = 0;
- // --- Simulation state ---
- float transX = spawnX, transY = spawnY, transZ = spawnZ;
- float pitch = 0, roll = 0, yaw = 0;
- bool firstPerson = false, freeCam = false, gameOver = false;
- // --- Camera ---
- Camera camera = { 0 };
- camera.position = (Vector3){0, 60, 120};
- camera.target = (Vector3){0, 10, 0};
- camera.up = (Vector3){0, 1, 0};
- camera.fovy = 8.0f;
- camera.projection = CAMERA_PERSPECTIVE;
- // --- Landing spot ---
- Vector3 landingSpot = {100.0f, 27.458f, 1.0f};
- const float collisionThreshold = 5.0f;
- // --- Menu flags ---
- bool inMenu = true;
- bool gameStarted = false;
- // --- Main loop ---
- while (!WindowShouldClose())
- {
- int W = GetScreenWidth();
- int H = GetScreenHeight();
- // Only update audio when playing
- if (gameStarted) UpdateMusicStream(engineSound);
- // Input: toggle views
- if (gameStarted && !gameOver)
- {
- if (IsKeyPressed(KEY_F)) firstPerson = !firstPerson;
- if (IsKeyPressed(KEY_R)) freeCam = !freeCam;
- }
- // Simulation update
- if (gameStarted && !gameOver)
- {
- const float groundAlt = 6000.0f;
- const float constantGravity = 0.5f;
- float speedFactor = 1.0f;
- if (transY <= groundAlt)
- {
- transY -= constantGravity;
- speedFactor = 0.5f;
- }
- Vector3 forward = { sinf(DEG2RAD*yaw), 0, cosf(DEG2RAD*yaw) };
- if (IsKeyDown(KEY_LEFT_SHIFT))
- {
- transX += forward.x * 40.5f * speedFactor;
- transZ += forward.z * 40.5f * speedFactor;
- transY += sinf(DEG2RAD*pitch) * 20.5f * speedFactor;
- }
- if (IsKeyDown(KEY_SPACE))
- {
- transX += forward.x * 50.0f * speedFactor;
- transZ += forward.z * 50.0f * speedFactor;
- }
- if (IsKeyDown(KEY_W)) transY += 12.0f * speedFactor;
- if (IsKeyDown(KEY_S)) transY -= 12.0f * speedFactor;
- if (IsKeyDown(KEY_DOWN)) pitch += 0.2f;
- else if (IsKeyDown(KEY_UP)) pitch -= 0.2f;
- else if (pitch > 0.2f) pitch -= 0.2f;
- else if (pitch < -0.2f) pitch += 0.2f;
- if (IsKeyDown(KEY_D)) yaw -= 0.4f;
- if (IsKeyDown(KEY_A)) yaw += 0.4f;
- if (IsKeyDown(KEY_LEFT)) roll -= 0.7f;
- else if (IsKeyDown(KEY_RIGHT)) roll += 0.7f;
- else if (roll > 0.0f) roll -= 0.3f;
- else if (roll < 0.0f) roll += 0.3f;
- transX = Clamp(transX, -189900.0f, 9900.0f);
- transZ = Clamp(transZ, -9900.0f, 189900.0f);
- transY = Clamp(transY, 5500.0f, 200000.0f);
- Matrix rotM = MatrixRotateXYZ((Vector3){DEG2RAD*pitch, DEG2RAD*yaw, DEG2RAD*roll});
- Matrix transM = MatrixTranslate(transX, transY, transZ);
- planeModel.transform = MatrixMultiply(rotM, MatrixMultiply(transM, MatrixMultiply(corrM, scaleM)));
- Vector3 planePos = { planeModel.transform.m12, planeModel.transform.m13, planeModel.transform.m14 };
- if (Vector3Distance(planePos, landingSpot) < collisionThreshold) gameOver = true;
- }
- // Camera update
- if (gameStarted && !freeCam)
- {
- Vector3 ppos = { planeModel.transform.m12, planeModel.transform.m13, planeModel.transform.m14 };
- if (firstPerson)
- {
- camera.position = Vector3Add(ppos, (Vector3){0,0.5f,0});
- Matrix pr = MatrixRotateXYZ((Vector3){DEG2RAD*pitch, DEG2RAD*yaw, DEG2RAD*roll});
- Matrix cm = MatrixMultiply(pr, corrM);
- camera.target = Vector3Add(camera.position, Vector3Transform((Vector3){0,0,1}, cm));
- camera.up = Vector3Transform((Vector3){0,1,0}, cm);
- }
- else
- {
- Matrix fr = MatrixRotateXYZ((Vector3){DEG2RAD*pitch, DEG2RAD*yaw, 0});
- Vector3 offset = Vector3Transform((Vector3){-15,2.5,0}, fr);
- Vector3 desired = Vector3Add(ppos, offset);
- camera.position = Vector3Lerp(camera.position, desired, 0.1f);
- camera.target = ppos;
- }
- }
- else if (freeCam)
- {
- UpdateCamera(&camera, CAMERA_FREE);
- }
- // --- DRAW ---
- BeginDrawing();
- ClearBackground(inMenu ? RAYWHITE : SKYBLUE);
- if (inMenu)
- {
- DrawText("Airplane Simulation",
- W/2 - MeasureText("Airplane Simulation", 40)/2,
- H/2 - 120, 40, DARKBLUE);
- if (GuiButton((Rectangle){W/2 -100, H/2 -40, 200, 50}, "Start"))
- {
- inMenu = false;
- gameStarted = true;
- gameOver = false;
- spawnedCount= 0;
- transX = spawnX; transY = spawnY; transZ = spawnZ;
- pitch = roll = yaw = 0;
- }
- if (GuiButton((Rectangle){W/2 -100, H/2 +20, 200, 50}, "Exit"))
- {
- CloseWindow();
- return 0;
- }
- }
- else // gameplay
- {
- BeginMode3D(camera);
- DrawModel(terrain, (Vector3){-50,0,-50}, 1.0f, WHITE);
- DrawGrid(500,1);
- DrawModel(runway, (Vector3){95,27.458f,15}, 1.0f, WHITE);
- // --- Draw Planes ---
- // First, draw the player-controlled plane. Its transform is already set from the simulation update.
- DrawModel(planeModel, (Vector3){0,0,0}, 1.0f, WHITE);
- // Now, draw the other spawned planes.
- // To do this without messing up the player plane's transform for the next frame,
- // we'll save it, draw the other planes by temporarily changing the transform,
- // and then restore it.
- Matrix playerTransform = planeModel.transform; // Save player's transform
- for (int i = 0; i < spawnedCount; i++)
- {
- planeModel.transform = spawned[i]; // Temporarily use the spawned plane's transform
- DrawModel(planeModel, (Vector3){0,0,0}, 1.0f, WHITE);
- }
- planeModel.transform = playerTransform; // Restore player's transform
- DrawSphere(landingSpot, 1.0f, RED);
- EndMode3D();
- DrawFPS(960,10);
- // <-- Add Planes
- Rectangle addBtn = { 20, 20, 140, 40 };
- // We can have a max of MAX_PLANES total. 1 is the player plane.
- if (GuiButton(addBtn, "Add Planes"))
- {
- if ((1 + spawnedCount) < MAX_PLANES)
- spawned[spawnedCount++] = baseSpawn;
- }
- // Now draw one lettered button per active plane.
- // There is always 1 (the player) + `spawnedCount` others.
- for (int i = 0; i < 1 + spawnedCount; i++)
- {
- // Position each button below the last, starting below the "Add Planes" button
- Rectangle letterBtn = {
- addBtn.x,
- addBtn.y + addBtn.height + 10 + (i * (addBtn.height + 10)),
- addBtn.width,
- addBtn.height
- };
- char label[2] = { 'A' + i, '\0' }; // "A", "B", "C", etc.
- // When a button is clicked, you could use its index 'i'
- // to select that plane for camera focus or control.
- if (GuiButton(letterBtn, label))
- {
- // For future use:
- // if (i == 0) {
- // // This is the player's plane (Plane A)
- // } else {
- // // This is a spawned plane (B, C, ...). Its index in the `spawned` array is `i - 1`.
- // // For example: select spawned[i - 1]
- // }
- }
- }
- // Game Over overlay
- if (gameOver)
- {
- DrawRectangle(0,0,W,H, Fade(BLACK, 0.5f));
- DrawText("LANDED!",
- W/2 - MeasureText("LANDED!", 40)/2,
- H/2 - 50, 40, WHITE);
- DrawText("Press Y to Play Again or N to Exit",
- W/2 - MeasureText("Press Y to Play Again or N to Exit", 20)/2,
- H/2 + 10, 20, WHITE);
- if (IsKeyPressed(KEY_Y))
- {
- gameOver = false;
- spawnedCount = 0;
- transX = spawnX; transY = spawnY; transZ = spawnZ;
- pitch = roll = yaw = 0;
- }
- if (IsKeyPressed(KEY_N)) break;
- }
- }
- EndDrawing();
- }
- // --- Cleanup ---
- CloseAudioDevice();
- UnloadMusicStream(engineSound);
- UnloadModel(terrain); UnloadTexture(terrainTex); UnloadShader(sat);
- UnloadModel(planeModel); UnloadTexture(planeTex);
- UnloadModel(runway); UnloadTexture(runwayTex);
- CloseWindow();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment