Compare commits
2 Commits
3ceddfb554
...
897b33a57a
| Author | SHA1 | Date | |
|---|---|---|---|
| 897b33a57a | |||
| b2369d5171 |
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Build artifacts
|
||||
a.out
|
||||
*.o
|
||||
build/
|
||||
BIN
bad_sphere.glb
Normal file
1
build.sh
Executable file
@@ -0,0 +1 @@
|
||||
cc main.c -lraylib -lGL -lm -lpthread -ldl -lrt -lX11
|
||||
BIN
diard-charles.jpg
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
grass_textures/Grass_01.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_01_Nrm.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_02.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_02_Nrm.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_03.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_03_Nrm.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_04.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
grass_textures/Grass_04_Nrm.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
little_mouse_warrior.glb
Normal file
559
main.c
Normal file
@@ -0,0 +1,559 @@
|
||||
#include "raylib.h"
|
||||
#include "rcamera.h"
|
||||
#include "raymath.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
// Movement constants
|
||||
#define GRAVITY 32.0f
|
||||
#define MAX_SPEED 20.0f
|
||||
#define CROUCH_SPEED 5.0f
|
||||
#define JUMP_FORCE 12.0f
|
||||
#define MAX_ACCEL 150.0f
|
||||
|
||||
// Grounded drag
|
||||
#define FRICTION 0.86f
|
||||
|
||||
// Increasing air drag, increases strafing speed
|
||||
#define AIR_DRAG 0.98f
|
||||
|
||||
// Responsiveness for turning movement direction to looked direction
|
||||
#define CONTROL 15.0f
|
||||
#define CROUCH_HEIGHT 0.0f
|
||||
#define STAND_HEIGHT 2.0f
|
||||
#define BOTTOM_HEIGHT 0.5f
|
||||
|
||||
// Additional definitions
|
||||
#define NORMALIZE_INPUT 0
|
||||
#define ARRLEN(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
enum game_state {
|
||||
STATE_MENU, // 0 by default
|
||||
STATE_GAME, // 1
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//Defining program structure
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Camera camera; // <- now part of the game state
|
||||
Model model; // you can keep model & its position here too
|
||||
Vector3 position;
|
||||
Vector3 velocity;
|
||||
Vector3 dir;
|
||||
Vector2 sensitivity;
|
||||
Vector2 lookRotation;
|
||||
Vector2 lean;
|
||||
float headTimer;
|
||||
float walkLerp;
|
||||
float headLerp;
|
||||
bool isGrounded;
|
||||
int cameraMode;
|
||||
} Player;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int index;
|
||||
enum game_state state;
|
||||
int shouldExit;
|
||||
Player player;
|
||||
} Master;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Function Initation
|
||||
//------------------------------------------------------------------------------------
|
||||
void Simple_Center_Box(double percent_verticle_gap, double percent_horizontal_gap, int screenWidth, int screenHeight, Color color);
|
||||
void Thick_Center_Box(double percent_verticle_gap, double percent_horizontal_gap, float line_width, int screenWidth, int screenHeight, Color color);
|
||||
void Simple_Menu(const char *array[], int count, int index, int x1, int y1, int total_width, int total_height, int line_thickess, int font_size, Color color, Color alt_color);
|
||||
void UpdateBody(Master* g, float rot, char side, char forward, bool jumpPressed, bool crouchHold);
|
||||
static void UpdateCameraAngle(Master* g);
|
||||
static void DrawLevel(Model mdlTile);
|
||||
static void CenterMouseAndFlush(void);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
//Define window size, create window, establish fps target, fullscreen.
|
||||
const int screenWidth = 1440*2;
|
||||
const int screenHeight = 960*2;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib");
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
ToggleFullscreen();
|
||||
CenterMouseAndFlush();
|
||||
DisableCursor(); // Limit cursor to relative movement inside the window
|
||||
|
||||
//Define menu characteristics
|
||||
const char *menu[] = {"Game", "Option 2", "Exit"};
|
||||
int index_length = ARRLEN(menu);
|
||||
|
||||
//General game state initiation
|
||||
Master g = (Master){0};
|
||||
g.index = 0;
|
||||
g.state = STATE_MENU;
|
||||
g.shouldExit = 0;
|
||||
|
||||
//Define
|
||||
g.player.sensitivity = (Vector2){ 0.001f, 0.001f };
|
||||
g.player.lookRotation = (Vector2){ 0 };
|
||||
g.player.headTimer = 0.0f;
|
||||
g.player.walkLerp = 0.0f;
|
||||
g.player.headLerp = STAND_HEIGHT;
|
||||
g.player.lean = (Vector2){ 0 };
|
||||
|
||||
//Define the player camera
|
||||
g.player.camera = (Camera){0};
|
||||
g.player.camera.position = (Vector3){
|
||||
g.player.position.x,
|
||||
g.player.position.y + (BOTTOM_HEIGHT + g.player.headLerp),
|
||||
g.player.position.z,
|
||||
};
|
||||
|
||||
//g.player.camera.target = (Vector3){ 0.0f, 0.0f, 1.0f }; // Camera target
|
||||
g.player.camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Up vector
|
||||
g.player.camera.fovy = 60.0f;
|
||||
g.player.camera.projection = CAMERA_PERSPECTIVE;
|
||||
g.player.cameraMode = CAMERA_FIRST_PERSON;
|
||||
|
||||
UpdateCameraAngle(&g);
|
||||
|
||||
// Load GLTF model (no animations)
|
||||
//Model model = LoadModel("bad_sphere.glb");
|
||||
//Vector3 position = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// Load a 2D image as texture for the billboard
|
||||
//Billboards always point toward the active camera.
|
||||
Texture2D sign = LoadTexture("diard-charles.jpg");
|
||||
GenTextureMipmaps(&sign);
|
||||
SetTextureFilter(sign, TEXTURE_FILTER_BILINEAR); // optional but looks nicer
|
||||
Vector3 bbPos = (Vector3){ 1.0f, 2.5f, 1.0f }; // where in 3D world to place it
|
||||
float bbSize = 5.0f; // billboard height in world units
|
||||
|
||||
// Load a 2D image as texture for the billboard
|
||||
//Billboards always point toward the active camera.
|
||||
Texture2D tree = LoadTexture("tree.png");
|
||||
GenTextureMipmaps(&tree);
|
||||
SetTextureFilter(tree, TEXTURE_FILTER_BILINEAR); // optional but looks nicer
|
||||
Vector3 treepos = (Vector3){ 0.0f, 7.0f, 0.0f }; // where in 3D world to place it
|
||||
float treeSize = 15.0f; // billboard height in world units
|
||||
|
||||
// --- Grass tile setup ---
|
||||
Texture2D texGrass = LoadTexture("grass_textures/Grass_01.png"); // adjust path
|
||||
GenTextureMipmaps(&texGrass);
|
||||
SetTextureFilter(texGrass, TEXTURE_FILTER_TRILINEAR); // nicer at angles
|
||||
SetTextureWrap(texGrass, TEXTURE_WRAP_REPEAT);
|
||||
|
||||
// A 3D plane (centered at origin) of size tileSize x tileSize
|
||||
const float tileSize = 5.0f; // match your DrawLevel tileSize
|
||||
Mesh meshTile = GenMeshPlane(tileSize, tileSize, 1, 1);
|
||||
Model mdlTile = LoadModelFromMesh(meshTile);
|
||||
mdlTile.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = texGrass;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
//--------------------------------------------------------------------------------------
|
||||
while (!g.shouldExit && !WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
switch (g.state)
|
||||
{
|
||||
case STATE_MENU:
|
||||
{
|
||||
if (IsKeyPressed(KEY_UP) && g.index > 0)
|
||||
{
|
||||
g.index -= 1;
|
||||
break;
|
||||
};
|
||||
|
||||
if (IsKeyPressed(KEY_DOWN) && g.index < index_length - 1)
|
||||
{
|
||||
g.index += 1;
|
||||
break;
|
||||
};
|
||||
|
||||
if (IsKeyPressed(KEY_ENTER))
|
||||
{
|
||||
switch (g.index)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
g.state = 1;
|
||||
CenterMouseAndFlush();
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
g.shouldExit = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
break;
|
||||
};
|
||||
case STATE_GAME:
|
||||
{
|
||||
Vector2 mouseDelta = GetMouseDelta();
|
||||
g.player.lookRotation.x -= mouseDelta.x*g.player.sensitivity.x;
|
||||
g.player.lookRotation.y += mouseDelta.y*g.player.sensitivity.y;
|
||||
|
||||
char sideway = (IsKeyDown(KEY_D) - IsKeyDown(KEY_A));
|
||||
char forward = (IsKeyDown(KEY_W) - IsKeyDown(KEY_S));
|
||||
bool crouching = IsKeyDown(KEY_LEFT_CONTROL);
|
||||
UpdateBody(&g, g.player.lookRotation.x, sideway, forward, IsKeyDown(KEY_SPACE), crouching);
|
||||
|
||||
float delta = GetFrameTime();
|
||||
g.player.headLerp = Lerp(g.player.headLerp, (crouching ? CROUCH_HEIGHT : STAND_HEIGHT), 20.0f*delta);
|
||||
g.player.camera.position = (Vector3){
|
||||
g.player.position.x,
|
||||
g.player.position.y + (BOTTOM_HEIGHT + g.player.headLerp),
|
||||
g.player.position.z,
|
||||
};
|
||||
|
||||
if (g.player.isGrounded && ((forward != 0) || (sideway != 0)))
|
||||
{
|
||||
g.player.headTimer += delta*3.0f;
|
||||
g.player.walkLerp = Lerp(g.player.walkLerp, 1.0f, 10.0f*delta);
|
||||
g.player.camera.fovy = Lerp(g.player.camera.fovy, 55.0f, 5.0f*delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.player.walkLerp = Lerp(g.player.walkLerp, 0.0f, 10.0f*delta);
|
||||
g.player.camera.fovy = Lerp(g.player.camera.fovy, 60.0f, 5.0f*delta);
|
||||
}
|
||||
|
||||
g.player.lean.x = Lerp(g.player.lean.x, sideway*0.02f, 10.0f*delta);
|
||||
g.player.lean.y = Lerp(g.player.lean.y, forward*0.015f, 10.0f*delta);
|
||||
|
||||
UpdateCameraAngle(&g);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int bbdifx = g.player.position.x - bbPos.x;
|
||||
int bbdifz = g.player.position.z - bbPos.z;
|
||||
|
||||
bbPos.x += 0.01 * bbdifx;
|
||||
bbPos.z += 0.01 * bbdifz;
|
||||
|
||||
treepos = (Vector3){ 0.0f, 7.0f, 0.0f };
|
||||
|
||||
break;
|
||||
};
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
switch (g.state)
|
||||
{
|
||||
case STATE_MENU:
|
||||
{
|
||||
ClearBackground(BLACK);
|
||||
|
||||
Simple_Menu(menu, ARRLEN(menu), g.index, screenWidth * 0.15, screenHeight * 0.15, 500, screenHeight * 0.7, 10, 50, GREEN, LIGHTGRAY);
|
||||
|
||||
Thick_Center_Box(0.1, 0.1, 10, screenWidth, screenHeight, GREEN);
|
||||
break;
|
||||
}
|
||||
case STATE_GAME:
|
||||
{
|
||||
ClearBackground(BLACK);
|
||||
|
||||
BeginMode3D(g.player.camera);
|
||||
DrawLevel(mdlTile);
|
||||
DrawBillboard(g.player.camera, sign, bbPos, bbSize, WHITE);
|
||||
|
||||
DrawBillboard(g.player.camera, tree, treepos, treeSize, WHITE);
|
||||
|
||||
treepos.x += 3*5;
|
||||
treepos.z += 3*5;
|
||||
DrawBillboard(g.player.camera, tree, treepos, treeSize, WHITE);
|
||||
|
||||
treepos.x += 5*5;
|
||||
treepos.z += -2*5;
|
||||
DrawBillboard(g.player.camera, tree, treepos, treeSize, WHITE);
|
||||
|
||||
treepos.x += -4*5;
|
||||
treepos.z += 3*5;
|
||||
DrawBillboard(g.player.camera, tree, treepos, treeSize, WHITE);
|
||||
|
||||
treepos.x += 9*5;
|
||||
treepos.z += 10*5;
|
||||
DrawBillboard(g.player.camera, tree, treepos, treeSize, WHITE);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
// Draw info box
|
||||
DrawRectangle(5, 5, 330, 75, Fade(SKYBLUE, 0.5f));
|
||||
DrawRectangleLines(5, 5, 330, 75, BLUE);
|
||||
|
||||
DrawText("Camera controls:", 15, 15, 10, BLACK);
|
||||
DrawText("- Move keys: W, A, S, D, Space, Left-Ctrl", 15, 30, 10, BLACK);
|
||||
DrawText("- Look around: arrow keys or mouse", 15, 45, 10, BLACK);
|
||||
DrawText(TextFormat("- Velocity Len: (%06.3f)", Vector2Length((Vector2){ g.player.velocity.x, g.player.velocity.z })), 15, 60, 10, BLACK);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
};
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Detach the texture from the model so UnloadModel won't try to free it.
|
||||
mdlTile.materials[0].maps[MATERIAL_MAP_ALBEDO].texture = (Texture2D){0};
|
||||
|
||||
// Now free resources you loaded:
|
||||
UnloadModel(mdlTile); // frees the model and its mesh/VBOs
|
||||
UnloadTexture(texGrass); // frees the grass texture you loaded
|
||||
UnloadTexture(sign); // frees billboard texture
|
||||
UnloadTexture(tree); // frees tree texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
return 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Function Definitions
|
||||
//------------------------------------------------------------------------------------
|
||||
//Function creates a simple box outline centered in the screen with a symetric ofset from the screen borders.
|
||||
void Simple_Center_Box(double percent_verticle_gap, double percent_horizontal_gap, int screenWidth, int screenHeight, Color color)
|
||||
{
|
||||
int x1 = percent_horizontal_gap * screenWidth;
|
||||
int y1 = percent_verticle_gap * screenHeight;
|
||||
|
||||
int w = screenWidth * (1 - (2 * percent_horizontal_gap));
|
||||
int h = screenHeight * (1 - (2 * percent_verticle_gap));
|
||||
|
||||
DrawRectangleLines(x1, y1, w, h, color);
|
||||
}
|
||||
|
||||
//Function creates a thick walled box outline centered in the screen with a symetric ofset from the screen borders.
|
||||
void Thick_Center_Box(double percent_verticle_gap, double percent_horizontal_gap, float line_width, int screenWidth, int screenHeight, Color color)
|
||||
{
|
||||
int x1 = percent_horizontal_gap * screenWidth;
|
||||
int y1 = percent_verticle_gap * screenHeight;
|
||||
|
||||
int w = screenWidth * (1 - (2 * percent_horizontal_gap));
|
||||
int h = screenHeight * (1 - (2 * percent_verticle_gap));
|
||||
|
||||
struct Rectangle rec = {x1,y1,w,h};
|
||||
|
||||
DrawRectangleLinesEx(rec, line_width, color);
|
||||
}
|
||||
|
||||
//Make a simple menu with selection features
|
||||
void Simple_Menu(const char *array[], int count, int index, int x1, int y1, int total_width, int total_height, int line_thickess, int font_size, Color color, Color alt_color)
|
||||
{
|
||||
float height = 0.8f * total_height;
|
||||
int space = 0.2 * total_height / (count - 1);
|
||||
|
||||
struct Rectangle rec = {x1,y1,total_width,(float)height/count};
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
int text_width = MeasureText(array[i], font_size);
|
||||
|
||||
if(i == index)
|
||||
{
|
||||
DrawRectangleLinesEx(rec, line_thickess, alt_color);
|
||||
DrawText(array[i], rec.x + (((total_width - 2.0 * line_thickess) - text_width)/2), rec.y + (height/count/2) - font_size/2.0f, font_size, alt_color);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawRectangleLinesEx(rec, line_thickess, color);
|
||||
DrawText(array[i], rec.x + (((total_width - 2.0 * line_thickess) - text_width)/2), rec.y + (height/count/2) - font_size/2.0f, font_size, color);
|
||||
}
|
||||
|
||||
rec.y = rec.y + (float)height/count + space;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateBody(Master* g, float rot, char side, char forward, bool jumpPressed, bool crouchHold)
|
||||
{
|
||||
Vector2 input = (Vector2){ (float)side, (float)-forward };
|
||||
|
||||
#if defined(NORMALIZE_INPUT)
|
||||
// Slow down diagonal movement
|
||||
if ((side != 0) && (forward != 0)) input = Vector2Normalize(input);
|
||||
#endif
|
||||
|
||||
float delta = GetFrameTime();
|
||||
|
||||
if (!g->player.isGrounded) g->player.velocity.y -= GRAVITY*delta;
|
||||
|
||||
if (g->player.isGrounded && jumpPressed)
|
||||
{
|
||||
g->player.velocity.y = JUMP_FORCE;
|
||||
g->player.isGrounded = false;
|
||||
|
||||
// Sound can be played at this moment
|
||||
//SetSoundPitch(fxJump, 1.0f + (GetRandomValue(-100, 100)*0.001));
|
||||
//PlaySound(fxJump);
|
||||
}
|
||||
|
||||
Vector3 front = (Vector3){ sin(rot), 0.f, cos(rot) };
|
||||
Vector3 right = (Vector3){ cos(-rot), 0.f, sin(-rot) };
|
||||
|
||||
Vector3 desiredDir = (Vector3){ input.x*right.x + input.y*front.x, 0.0f, input.x*right.z + input.y*front.z, };
|
||||
g->player.dir = Vector3Lerp(g->player.dir, desiredDir, CONTROL*delta);
|
||||
|
||||
float decel = (g->player.isGrounded ? FRICTION : AIR_DRAG);
|
||||
Vector3 hvel = (Vector3){ g->player.velocity.x*decel, 0.0f, g->player.velocity.z*decel };
|
||||
|
||||
float hvelLength = Vector3Length(hvel); // Magnitude
|
||||
if (hvelLength < (MAX_SPEED*0.01f)) hvel = (Vector3){ 0 };
|
||||
|
||||
// This is what creates strafing
|
||||
float speed = Vector3DotProduct(hvel, g->player.dir);
|
||||
|
||||
// Whenever the amount of acceleration to add is clamped by the maximum acceleration constant,
|
||||
// a Player can make the speed faster by bringing the direction closer to horizontal velocity angle
|
||||
// More info here: https://youtu.be/v3zT3Z5apaM?t=165
|
||||
float maxSpeed = (crouchHold? CROUCH_SPEED : MAX_SPEED);
|
||||
float accel = Clamp(maxSpeed - speed, 0.f, MAX_ACCEL*delta);
|
||||
hvel.x += g->player.dir.x*accel;
|
||||
hvel.z += g->player.dir.z*accel;
|
||||
|
||||
g->player.velocity.x = hvel.x;
|
||||
g->player.velocity.z = hvel.z;
|
||||
|
||||
g->player.position.x += g->player.velocity.x*delta;
|
||||
g->player.position.y += g->player.velocity.y*delta;
|
||||
g->player.position.z += g->player.velocity.z*delta;
|
||||
|
||||
// Fancy collision system against the floor
|
||||
if (g->player.position.y <= 0.0f)
|
||||
{
|
||||
g->player.position.y = 0.0f;
|
||||
g->player.velocity.y = 0.0f;
|
||||
g->player.isGrounded = true; // Enable jumping
|
||||
}
|
||||
}
|
||||
|
||||
// Update camera
|
||||
static void UpdateCameraAngle(Master* g)
|
||||
{
|
||||
const Vector3 up = (Vector3){ 0.0f, 1.0f, 0.0f };
|
||||
const Vector3 targetOffset = (Vector3){ 0.0f, 0.0f, -1.0f };
|
||||
|
||||
// Left and right
|
||||
Vector3 yaw = Vector3RotateByAxisAngle(targetOffset, up, g->player.lookRotation.x);
|
||||
|
||||
// Clamp view up
|
||||
float maxAngleUp = Vector3Angle(up, yaw);
|
||||
maxAngleUp -= 0.001f; // Avoid numerical errors
|
||||
if ( -(g->player.lookRotation.y) > maxAngleUp) { g->player.lookRotation.y = -maxAngleUp; }
|
||||
|
||||
// Clamp view down
|
||||
float maxAngleDown = Vector3Angle(Vector3Negate(up), yaw);
|
||||
maxAngleDown *= -1.0f; // Downwards angle is negative
|
||||
maxAngleDown += 0.001f; // Avoid numerical errors
|
||||
if ( -(g->player.lookRotation.y) < maxAngleDown) { g->player.lookRotation.y = -maxAngleDown; }
|
||||
|
||||
// Up and down
|
||||
Vector3 right = Vector3Normalize(Vector3CrossProduct(yaw, up));
|
||||
|
||||
// Rotate view vector around right axis
|
||||
float pitchAngle = -g->player.lookRotation.y -
|
||||
g->player.lean.y;
|
||||
pitchAngle = Clamp(pitchAngle, -PI / 2 + 0.0001f, PI / 2 - 0.0001f); // Clamp angle so it doesn't go past straight up or straight down
|
||||
Vector3 pitch = Vector3RotateByAxisAngle(yaw, right, pitchAngle);
|
||||
|
||||
// Head animation
|
||||
// Rotate up direction around forward axis
|
||||
float headSin = sin(g->player.headTimer*PI);
|
||||
float headCos = cos(g->player.headTimer*PI);
|
||||
const float stepRotation = 0.005f;
|
||||
g->player.camera.up = Vector3RotateByAxisAngle(up, pitch, headSin*stepRotation + g->player.lean.x);
|
||||
|
||||
// Camera BOB
|
||||
const float bobSide = 0.01f;
|
||||
const float bobUp = 0.01f;
|
||||
Vector3 bobbing = Vector3Scale(right, headSin*bobSide);
|
||||
bobbing.y = fabsf(headCos*bobUp);
|
||||
|
||||
g->player.camera.position = Vector3Add(g->player.camera.position, Vector3Scale(bobbing, g->player.walkLerp));
|
||||
g->player.camera.target = Vector3Add(g->player.camera.position, pitch);
|
||||
}
|
||||
|
||||
// Draw game level
|
||||
static void DrawLevel(Model mdlTile)
|
||||
{
|
||||
const int floorExtent = 25;
|
||||
const float tileSize = 5.0f;
|
||||
const Color tileColor1 = (Color){ 150, 200, 200, 255 };
|
||||
|
||||
// Floor tiles
|
||||
for (int y = -floorExtent; y < floorExtent; y++)
|
||||
{
|
||||
for (int x = -floorExtent; x < floorExtent; x++)
|
||||
{
|
||||
/*
|
||||
if ((y & 1) && (x & 1))
|
||||
{
|
||||
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, tileColor1);
|
||||
}
|
||||
else if (!(y & 1) && !(x & 1))
|
||||
{
|
||||
DrawPlane((Vector3){ x*tileSize, 0.0f, y*tileSize}, (Vector2){ tileSize, tileSize }, LIGHTGRAY);
|
||||
}
|
||||
*/
|
||||
Vector3 pos = (Vector3){ x*tileSize, 0.0f, y*tileSize };
|
||||
// mdlTile must be accessible here: make it global/static or pass it in
|
||||
DrawModel(mdlTile, pos, 1.0f, WHITE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
const Vector3 towerSize = (Vector3){ 16.0f, 32.0f, 16.0f };
|
||||
const Color towerColor = (Color){ 150, 200, 200, 255 };
|
||||
|
||||
Vector3 towerPos = (Vector3){ 16.0f, 16.0f, 16.0f };
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
towerPos.x *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
towerPos.z *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
towerPos.x *= -1;
|
||||
DrawCubeV(towerPos, towerSize, towerColor);
|
||||
DrawCubeWiresV(towerPos, towerSize, DARKBLUE);
|
||||
|
||||
// Red sun
|
||||
DrawSphere((Vector3){ 300.0f, 300.0f, 0.0f }, 100.0f, (Color){ 255, 0, 0, 255 });
|
||||
*/
|
||||
}
|
||||
|
||||
//fix mouse
|
||||
static void CenterMouseAndFlush() {
|
||||
SetMousePosition(GetRenderWidth()/2, GetRenderHeight()/2);
|
||||
(void)GetMouseDelta();
|
||||
}
|
||||