diff options
| author | raysan5 <[email protected]> | 2016-02-20 20:25:01 +0100 |
|---|---|---|
| committer | raysan5 <[email protected]> | 2016-02-20 20:25:01 +0100 |
| commit | 7b360d8579c63658ee05377b44d2e0b478d12b74 (patch) | |
| tree | 16c1553ba117869aeb370ae40f99bb4086701b55 /games/missile_commander.c | |
| parent | 83459159f4c8622cefe93a062138e7e2391b6761 (diff) | |
| download | raylib-7b360d8579c63658ee05377b44d2e0b478d12b74.tar.gz raylib-7b360d8579c63658ee05377b44d2e0b478d12b74.zip | |
Reorganized games folder
Simplified to match raylib installer package folder structure
Diffstat (limited to 'games/missile_commander.c')
| -rw-r--r-- | games/missile_commander.c | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/games/missile_commander.c b/games/missile_commander.c new file mode 100644 index 00000000..6317c41a --- /dev/null +++ b/games/missile_commander.c @@ -0,0 +1,539 @@ +/******************************************************************************************* +* +* raylib - sample game: missile commander +* +* Sample game Marc Palau and Ramon Santamaria +* +* This game has been created using raylib v1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <math.h> + +#if defined(PLATFORM_WEB) + #include <emscripten/emscripten.h> +#endif + +//---------------------------------------------------------------------------------- +// Some Defines +//---------------------------------------------------------------------------------- +#define MAX_MISSILES 100 +#define MAX_INTERCEPTORS 30 +#define MAX_EXPLOSIONS 100 +#define LAUNCHERS_AMOUNT 3 // Not a variable, should not be changed +#define BUILDINGS_AMOUNT 6 // Not a variable, should not be changed + +#define LAUNCHER_SIZE 80 +#define BUILDING_SIZE 60 +#define EXPLOSION_RADIUS 40 + +#define MISSILE_SPEED 1 +#define MISSILE_LAUNCH_FRAMES 80 +#define INTERCEPTOR_SPEED 10 +#define EXPLOSION_INCREASE_TIME 90 // In frames +#define EXPLOSION_TOTAL_TIME 210 // In frames + +#define EXPLOSION_COLOR (Color){ 125, 125, 125, 125 } + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct Missile { + Vector2 origin; + Vector2 position; + Vector2 objective; + Vector2 speed; + + bool active; +} Missile; + +typedef struct Interceptor { + Vector2 origin; + Vector2 position; + Vector2 objective; + Vector2 speed; + + bool active; +} Interceptor; + +typedef struct Explosion { + Vector2 position; + float radiusMultiplier; + int frame; + bool active; +} Explosion; + +typedef struct Launcher { + Vector2 position; + bool active; +} Launcher; + +typedef struct Building { + Vector2 position; + bool active; +} Building; + +//------------------------------------------------------------------------------------ +// Global Variables Declaration +//------------------------------------------------------------------------------------ +static int screenWidth = 800; +static int screenHeight = 450; + +static int framesCounter = 0; +static bool gameOver = false; +static bool pause = false; +static int score = 0; + +static Missile missile[MAX_MISSILES]; +static Interceptor interceptor[MAX_INTERCEPTORS]; +static Explosion explosion[MAX_EXPLOSIONS]; +static Launcher launcher[LAUNCHERS_AMOUNT]; +static Building building[BUILDINGS_AMOUNT]; +static int explosionIndex = 0; + +//------------------------------------------------------------------------------------ +// Module Functions Declaration (local) +//------------------------------------------------------------------------------------ +static void InitGame(void); // Initialize game +static void UpdateGame(void); // Update game (one frame) +static void DrawGame(void); // Draw game (one frame) +static void UnloadGame(void); // Unload game +static void UpdateDrawFrame(void); // Update and Draw (one frame) + +// Additional module functions +static void UpdateOutgoingFire(); +static void UpdateIncomingFire(); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "sample game: missile commander"); + + InitGame(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateGame(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + DrawGame(); + //---------------------------------------------------------------------------------- + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadGame(); // Unload loaded data (textures, sounds, models...) + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//-------------------------------------------------------------------------------------- +// Game Module Functions Definition +//-------------------------------------------------------------------------------------- + +// Initialize game variables +void InitGame(void) +{ + // Initialize missiles + for (int i = 0; i < MAX_MISSILES; i++) + { + missile[i].origin = (Vector2){ 0, 0 }; + missile[i].speed = (Vector2){ 0, 0 }; + missile[i].position = (Vector2){ 0, 0 }; + + missile[i].active = false; + } + + // Initialize interceptors + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + interceptor[i].origin = (Vector2){ 0, 0 }; + interceptor[i].speed = (Vector2){ 0, 0 }; + interceptor[i].position = (Vector2){ 0, 0 }; + + interceptor[i].active = false; + } + + // Initialize explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + explosion[i].position = (Vector2){ 0, 0 }; + explosion[i].frame = 0; + explosion[i].active = false; + } + + // Initialize buildings and launchers + int sparcing = screenWidth/(LAUNCHERS_AMOUNT + BUILDINGS_AMOUNT + 1); + + // Buildings and launchers placing + launcher[0].position = (Vector2){ 1*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + building[0].position = (Vector2){ 2*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[1].position = (Vector2){ 3*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[2].position = (Vector2){ 4*sparcing, screenHeight - BUILDING_SIZE/2 }; + launcher[1].position = (Vector2){ 5*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + building[3].position = (Vector2){ 6*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[4].position = (Vector2){ 7*sparcing, screenHeight - BUILDING_SIZE/2 }; + building[5].position = (Vector2){ 8*sparcing, screenHeight - BUILDING_SIZE/2 }; + launcher[2].position = (Vector2){ 9*sparcing, screenHeight - LAUNCHER_SIZE/2 }; + + // Buildings and launchers activation + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) launcher[i].active = true; + for (int i = 0; i < BUILDINGS_AMOUNT; i++) building[i].active = true; + + // Initialize game variables + score = 0; +} + +// Update game (one frame) +void UpdateGame(void) +{ + if (!gameOver) + { + if (IsKeyPressed('P')) pause = !pause; + + if (!pause) + { + framesCounter++; + + static + float distance; + + // Interceptors update + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + if (interceptor[i].active) + { + // Update position + interceptor[i].position.x += interceptor[i].speed.x; + interceptor[i].position.y += interceptor[i].speed.y; + + // Distance to objective + distance = sqrt( pow(interceptor[i].position.x - interceptor[i].objective.x, 2) + + pow(interceptor[i].position.y - interceptor[i].objective.y, 2)); + + if (distance < INTERCEPTOR_SPEED) + { + // Interceptor dissapears + interceptor[i].active = false; + + // Explosion + explosion[explosionIndex].position = interceptor[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // Missiles update + for (int i = 0; i < MAX_MISSILES; i++) + { + if (missile[i].active) + { + // Update position + missile[i].position.x += missile[i].speed.x; + missile[i].position.y += missile[i].speed.y; + + // Collision and missile out of bounds + if (missile[i].position.y > screenHeight) missile[i].active = false; + else + { + // CHeck collision with launchers + for (int j = 0; j < LAUNCHERS_AMOUNT; j++) + { + if (launcher[j].active) + { + if (CheckCollisionPointRec(missile[i].position, (Rectangle){ launcher[j].position.x - LAUNCHER_SIZE/2, launcher[j].position.y - LAUNCHER_SIZE/2, + LAUNCHER_SIZE, LAUNCHER_SIZE })) + { + // Missile dissapears + missile[i].active = false; + + // Explosion and destroy building + launcher[j].active = false; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // CHeck collision with buildings + for (int j = 0; j < BUILDINGS_AMOUNT; j++) + { + if (building[j].active) + { + if (CheckCollisionPointRec(missile[i].position, (Rectangle){ building[j].position.x - BUILDING_SIZE/2, building[j].position.y - BUILDING_SIZE/2, + BUILDING_SIZE, BUILDING_SIZE })) + { + // Missile dissapears + missile[i].active = false; + + // Explosion and destroy building + building[j].active = false; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + + // CHeck collision with explosions + for (int j = 0; j < MAX_EXPLOSIONS; j++) + { + if (explosion[j].active) + { + if (CheckCollisionPointCircle(missile[i].position, explosion[j].position, EXPLOSION_RADIUS*explosion[j].radiusMultiplier)) + { + // Missile dissapears and we earn 100 points + missile[i].active = false; + score += 100; + + explosion[explosionIndex].position = missile[i].position; + explosion[explosionIndex].active = true; + explosion[explosionIndex].frame = 0; + explosionIndex++; + if (explosionIndex == MAX_EXPLOSIONS) explosionIndex = 0; + + break; + } + } + } + } + } + } + + // Explosions update + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) + { + explosion[i].frame++; + + if (explosion[i].frame <= EXPLOSION_INCREASE_TIME) explosion[i].radiusMultiplier = explosion[i].frame/(float)EXPLOSION_INCREASE_TIME; + else if (explosion[i].frame <= EXPLOSION_TOTAL_TIME) explosion[i].radiusMultiplier = 1 - (explosion[i].frame - (float)EXPLOSION_INCREASE_TIME)/(float)EXPLOSION_TOTAL_TIME; + else + { + explosion[i].frame = 0; + explosion[i].active = false; + } + } + } + + // Fire logic + UpdateOutgoingFire(); + UpdateIncomingFire(); + + // Game over logic + int checker = 0; + + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) + { + if (!launcher[i].active) checker++; + if (checker == LAUNCHERS_AMOUNT) gameOver = true; + } + + checker = 0; + for (int i = 0; i < BUILDINGS_AMOUNT; i++) + { + if (!building[i].active) checker++; + if (checker == BUILDINGS_AMOUNT) gameOver = true; + } + } + } + else + { + if (IsKeyPressed(KEY_ENTER)) + { + InitGame(); + gameOver = false; + } + } +} + +// Draw game (one frame) +void DrawGame(void) +{ + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (!gameOver) + { + // Draw missiles + for (int i = 0; i < MAX_MISSILES; i++) + { + if (missile[i].active) + { + DrawLine(missile[i].origin.x, missile[i].origin.y, missile[i].position.x, missile[i].position.y, RED); + + if (framesCounter % 16 < 8) DrawCircle(missile[i].position.x, missile[i].position.y, 3, YELLOW); + } + } + + // Draw interceptors + for (int i = 0; i < MAX_INTERCEPTORS; i++) + { + if (interceptor[i].active) + { + DrawLine(interceptor[i].origin.x, interceptor[i].origin.y, interceptor[i].position.x, interceptor[i].position.y, GREEN); + + if (framesCounter % 16 < 8) DrawCircle(interceptor[i].position.x, interceptor[i].position.y, 3, BLUE); + } + } + + // Draw explosions + for (int i = 0; i < MAX_EXPLOSIONS; i++) + { + if (explosion[i].active) DrawCircle(explosion[i].position.x, explosion[i].position.y, EXPLOSION_RADIUS*explosion[i].radiusMultiplier, EXPLOSION_COLOR); + } + + // Draw buildings and launchers + for (int i = 0; i < LAUNCHERS_AMOUNT; i++) + { + if (launcher[i].active) DrawRectangle(launcher[i].position.x - LAUNCHER_SIZE/2, launcher[i].position.y - LAUNCHER_SIZE/2, LAUNCHER_SIZE, LAUNCHER_SIZE, GRAY); + } + + for (int i = 0; i < BUILDINGS_AMOUNT; i++) + { + if (building[i].active) DrawRectangle(building[i].position.x - BUILDING_SIZE/2, building[i].position.y - BUILDING_SIZE/2, BUILDING_SIZE, BUILDING_SIZE, LIGHTGRAY); + } + + // Draw score + DrawText(FormatText("SCORE %4i", score), 20, 20, 40, LIGHTGRAY); + + if (pause) DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY); + } + else DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY); + + EndDrawing(); +} + +// Unload game variables +void UnloadGame(void) +{ + // TODO: Unload all dynamic loaded data (textures, sounds, models...) +} + +// Update and Draw (one frame) +void UpdateDrawFrame(void) +{ + UpdateGame(); + DrawGame(); +} + +//-------------------------------------------------------------------------------------- +// Additional module functions +//-------------------------------------------------------------------------------------- +static void UpdateOutgoingFire() +{ + static int interceptorNumber = 0; + int launcherShooting = 0; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) launcherShooting = 1; + if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) launcherShooting = 2; + if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) launcherShooting = 3; + + if (launcherShooting > 0 && launcher[launcherShooting - 1].active) + { + float module; + float sideX; + float sideY; + + // Activate the interceptor + interceptor[interceptorNumber].active = true; + + // Assign start position + interceptor[interceptorNumber].origin = launcher[launcherShooting - 1].position; + interceptor[interceptorNumber].position = interceptor[interceptorNumber].origin; + interceptor[interceptorNumber].objective = GetMousePosition(); + + // Calculate speed + module = sqrt( pow(interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x, 2) + + pow(interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y, 2)); + + sideX = (interceptor[interceptorNumber].objective.x - interceptor[interceptorNumber].origin.x)*INTERCEPTOR_SPEED/module; + sideY = (interceptor[interceptorNumber].objective.y - interceptor[interceptorNumber].origin.y)*INTERCEPTOR_SPEED/module; + + interceptor[interceptorNumber].speed = (Vector2){ sideX, sideY }; + + // Update + interceptorNumber++; + if (interceptorNumber == MAX_INTERCEPTORS) interceptorNumber = 0; + } +} + +static void UpdateIncomingFire() +{ + static int missileIndex = 0; + + // Launch missile + if (framesCounter % MISSILE_LAUNCH_FRAMES == 0) + { + float module; + float sideX; + float sideY; + + // Activate the missile + missile[missileIndex].active = true; + + // Assign start position + missile[missileIndex].origin = (Vector2){ GetRandomValue(20, screenWidth - 20), -10 }; + missile[missileIndex].position = missile[missileIndex].origin; + missile[missileIndex].objective = (Vector2){ GetRandomValue(20, screenWidth - 20), screenHeight + 10 }; + + // Calculate speed + module = sqrt( pow(missile[missileIndex].objective.x - missile[missileIndex].origin.x, 2) + + pow(missile[missileIndex].objective.y - missile[missileIndex].origin.y, 2)); + + sideX = (missile[missileIndex].objective.x - missile[missileIndex].origin.x)*MISSILE_SPEED/module; + sideY = (missile[missileIndex].objective.y - missile[missileIndex].origin.y)*MISSILE_SPEED/module; + + missile[missileIndex].speed = (Vector2){ sideX, sideY }; + + // Update + missileIndex++; + if (missileIndex == MAX_MISSILES) missileIndex = 0; + } +}
\ No newline at end of file |
