├── res ├── audio │ ├── Boot.wav │ ├── Button.wav │ └── ButtonHover.wav ├── fonts │ └── Monocraft.ttf └── sprites │ └── player │ ├── idle.gif │ ├── move.gif │ ├── idle-down.gif │ ├── idle-up.gif │ ├── move-down.gif │ └── move-up.gif ├── Makefile ├── src ├── main.c ├── camera.h ├── game.h ├── texture.h ├── menu.h └── player.h ├── README.md └── LICENSE /res/audio/Boot.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/audio/Boot.wav -------------------------------------------------------------------------------- /res/audio/Button.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/audio/Button.wav -------------------------------------------------------------------------------- /res/fonts/Monocraft.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/fonts/Monocraft.ttf -------------------------------------------------------------------------------- /res/audio/ButtonHover.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/audio/ButtonHover.wav -------------------------------------------------------------------------------- /res/sprites/player/idle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/sprites/player/idle.gif -------------------------------------------------------------------------------- /res/sprites/player/move.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/sprites/player/move.gif -------------------------------------------------------------------------------- /res/sprites/player/idle-down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/sprites/player/idle-down.gif -------------------------------------------------------------------------------- /res/sprites/player/idle-up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/sprites/player/idle-up.gif -------------------------------------------------------------------------------- /res/sprites/player/move-down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/sprites/player/move-down.gif -------------------------------------------------------------------------------- /res/sprites/player/move-up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x3ric/raygame/HEAD/res/sprites/player/move-up.gif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | LIBS = -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 3 | SOURCES = ./src/*.c ./src/*.h 4 | TARGET = ./build/game 5 | all: 6 | $(CC) $(SOURCES) -o $(TARGET) $(LIBS) 7 | run: 8 | rm -f $(TARGET) 9 | $(CC) $(SOURCES) -o $(TARGET) $(LIBS) 10 | $(TARGET) 11 | clean: 12 | rm -rf ./build/game 13 | .PHONY: all clean -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "menu.h" 2 | #include "game.h" 3 | 4 | int main() 5 | { 6 | InitWindow(1920, 1080, "raylib game"); 7 | SetTargetFPS(60); 8 | InitAudioDevice(); 9 | goto start; //skip to game 10 | Boot(); 11 | switch(MainMenu()) { 12 | case 0: 13 | CloseWindow(); 14 | return 0; 15 | case 1: 16 | start: 17 | Game(); 18 | break; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/camera.h: -------------------------------------------------------------------------------- 1 | #ifndef CAMERA_H 2 | #define CAMERA_H 3 | 4 | #include "raylib.h" 5 | #include 6 | 7 | float cameraLerpFactor = 1.25f; 8 | Camera2D camera = { 0 }; 9 | 10 | void CameraInit() { 11 | float midx = GetScreenWidth()/2.0f; 12 | float midy = GetScreenHeight()/2.0f; 13 | camera.rotation = 0.0f; 14 | camera.zoom = 1.0f; 15 | camera.offset = (Vector2){ midx, midy }; 16 | camera.target = (Vector2){ 0, 0 }; 17 | } 18 | 19 | void CameraLoop(Vector2 PlayerPosition,float deltaTime) { 20 | camera.target.x += (PlayerPosition.x - camera.target.x) * cameraLerpFactor * deltaTime; 21 | camera.target.y += (PlayerPosition.y - camera.target.y) * cameraLerpFactor * deltaTime; 22 | } 23 | 24 | #endif // CAMERA_H -------------------------------------------------------------------------------- /src/game.h: -------------------------------------------------------------------------------- 1 | #ifndef GAME_H 2 | #define GAME_H 3 | 4 | #include "camera.h" 5 | #include "player.h" 6 | #include "texture.h" 7 | 8 | int Game() { 9 | CameraInit(); 10 | CheckedInit(); 11 | PlayerInit(); 12 | while(!WindowShouldClose()) { 13 | PlayerLoop(); 14 | CameraLoop(PlayerPosition,deltaTime); 15 | BeginDrawing(); 16 | ClearBackground(BLACK); 17 | DrawCenteredTiledTexture(checked,camera); 18 | BeginMode2D(camera); 19 | Player(); 20 | EndMode2D(); 21 | PlayerInfo(); 22 | EndDrawing(); 23 | } 24 | UnloadChecked(); 25 | UnloadPlayer(); 26 | CloseWindow(); 27 | return 0; 28 | } 29 | 30 | #endif // GAME_H -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ### Raylib TopDown Template 4 | 5 | This is a simple top-down game template built using the raylib library. 6 | 7 | It provides a starting point for creating your own top-down games using raylib. 8 | 9 | #### Features 10 | 11 | Simple top-down player movement 12 | 13 | Customizable game loop 14 | 15 | Easy-to-understand code structure 16 | 17 | #### Requirements 18 | 19 | raylib library ([Installation Guide](https://github.com/raysan5/raylib)) 20 | 21 | #### Compile & run 22 | 23 |
24 | git clone https://github.com/x3ric/raygame
25 | cd raygame
26 | make run
27 | 
28 | 29 |
30 |

Arch Linux
31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 X3ric 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/texture.h: -------------------------------------------------------------------------------- 1 | #ifndef TEXTURE_H 2 | #define TEXTURE_H 3 | 4 | #include "raylib.h" 5 | #include 6 | 7 | Texture2D checked; 8 | 9 | Texture2D CheckedTexture() { 10 | const int TILE_SIZE = 16; 11 | int width = TILE_SIZE * 16; 12 | int height = TILE_SIZE * 16; 13 | Color *pixels = (Color *)malloc(width*height*sizeof(Color)); 14 | for (int y = 0; y < height; y++) { 15 | for (int x = 0; x < width; x++) { 16 | if (((x/TILE_SIZE+y/TILE_SIZE)/1)%2 == 0) pixels[y*width + x] = PURPLE; 17 | //else pixels[y*width + x] = PURPLE; 18 | else pixels[y*width + x] = (Color){0.0,0.0,0.0}; 19 | } 20 | } 21 | Image checkedIm = { 22 | .data = pixels, 23 | .width = width, 24 | .height = height, 25 | .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, 26 | .mipmaps = 1 27 | }; 28 | Texture2D checked = LoadTextureFromImage(checkedIm); 29 | UnloadImage(checkedIm); 30 | return checked; 31 | } 32 | 33 | void DrawCenteredTiledTexture(Texture2D texture, Camera2D camera) { 34 | int screenWidth = GetScreenWidth(); 35 | int screenHeight = GetScreenHeight(); 36 | int centerX = 0; 37 | int centerY = 0; 38 | int startX = centerX - ((int)camera.target.x % texture.width); 39 | int startY = centerY - ((int)camera.target.y % texture.height); 40 | startX -= texture.width; 41 | startY -= texture.height; 42 | for (int y = startY; y < screenHeight + texture.height; y += texture.height) { 43 | for (int x = startX; x < screenWidth + texture.width; x += texture.width) { 44 | Rectangle sourceRec = { 0, 0, texture.width, texture.height}; 45 | // Left edge 46 | if (x < 0) { 47 | sourceRec.x = -x; 48 | sourceRec.width += x; 49 | } 50 | // Top edge 51 | if (y < 0) { 52 | sourceRec.y = -y; 53 | sourceRec.height += y; 54 | } 55 | // Right edge 56 | if (x + texture.width > screenWidth) { 57 | int overflowX = (x + texture.width) - screenWidth; 58 | sourceRec.width -= overflowX; 59 | } 60 | // Bottom edge 61 | if (y + texture.height > screenHeight) { 62 | int overflowY = (y + texture.height) - screenHeight; 63 | sourceRec.height -= overflowY; 64 | } 65 | Rectangle destRec = { x + sourceRec.x, y + sourceRec.y, sourceRec.width, sourceRec.height }; 66 | DrawTexturePro(texture, sourceRec, destRec, (Vector2){0, 0}, 0.0f, Fade(DARKGRAY, 0.5f)); 67 | } 68 | } 69 | } 70 | 71 | void DrawCenteredTexture(Texture2D texture) { 72 | int screenWidth = GetScreenWidth(); 73 | int screenHeight = GetScreenHeight(); 74 | int startX = (screenWidth / 2) % texture.width - texture.width; 75 | int startY = (screenHeight / 2) % texture.height - texture.height; 76 | for (int y = startY; y < screenHeight; y += texture.height) { 77 | for (int x = startX; x < screenWidth; x += texture.width) { 78 | DrawTexture(texture, x, y, Fade(DARKGRAY, 0.5f)); 79 | } 80 | } 81 | } 82 | 83 | void CheckedInit() { 84 | checked = CheckedTexture(); 85 | } 86 | 87 | void UnloadChecked() { 88 | UnloadTexture(checked); 89 | } 90 | 91 | #endif // TEXTURE_H 92 | -------------------------------------------------------------------------------- /src/menu.h: -------------------------------------------------------------------------------- 1 | #ifndef MENU_H 2 | #define MENU_H 3 | 4 | #include "raylib.h" 5 | #include "raymath.h" 6 | 7 | int MainMenu() { 8 | int BUTTON_HEIGHT = 50; 9 | int BUTTON_WIDTH = 200; 10 | Vector2 oldPos = {0.0f, 0.0f}; 11 | const char title[] = "Prototype"; 12 | bool ButtonFocused = false; 13 | Sound fxButton = LoadSound("./res/audio/Button.wav"); 14 | Sound fxButtonHover = LoadSound("./res/audio/ButtonHover.wav"); 15 | Font fontTtf = LoadFontEx("./res/fonts/Monocraft.ttf", 40, 0, 250); 16 | Vector2 textPosition = { 17 | GetScreenWidth()/2 - MeasureTextEx(fontTtf, title, 40, 0).x/2, 18 | GetScreenHeight()/2 - MeasureTextEx(fontTtf, title, 40, 0).y/2 - 100 19 | }; 20 | while(!WindowShouldClose()) 21 | { 22 | Vector2 startButtonPos = { (GetScreenWidth() - BUTTON_WIDTH) / 2, (GetScreenHeight() - 2 * BUTTON_HEIGHT) / 2 }; 23 | Vector2 exitButtonPos = { (GetScreenWidth() - BUTTON_WIDTH) / 2, (GetScreenHeight() + BUTTON_HEIGHT) / 2 }; 24 | if ((Vector2Distance(oldPos, GetMousePosition()) != 0.0f)&&(CheckCollisionPointRec(GetMousePosition(), (Rectangle){ startButtonPos.x, startButtonPos.y, BUTTON_WIDTH, BUTTON_HEIGHT }))) { 25 | if(ButtonFocused) {PlaySound(fxButtonHover);} 26 | ButtonFocused = false; 27 | if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ 28 | PlaySound(fxButton); 29 | return 1; 30 | } 31 | } else if ((Vector2Distance(oldPos, GetMousePosition()) != 0.0f)&&(CheckCollisionPointRec(GetMousePosition(), (Rectangle){ exitButtonPos.x, exitButtonPos.y, BUTTON_WIDTH, BUTTON_HEIGHT }))) { 32 | if(!ButtonFocused) {PlaySound(fxButtonHover);} 33 | ButtonFocused = true; 34 | if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)){ 35 | PlaySound(fxButton); 36 | return 0; 37 | } 38 | } else if (IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W) || IsKeyPressed(KEY_S) || IsKeyPressed(KEY_J) || IsKeyPressed(KEY_K)) { 39 | ButtonFocused = !ButtonFocused; 40 | PlaySound(fxButtonHover); 41 | } 42 | if (IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_SPACE)) { 43 | PlaySound(fxButton); 44 | if (!ButtonFocused) { 45 | return 1; 46 | } else { 47 | return 0; 48 | } 49 | } 50 | oldPos = GetMousePosition(); 51 | BeginDrawing(); 52 | ClearBackground(BLACK); 53 | DrawTextEx(fontTtf, title, textPosition, (float)fontTtf.baseSize, 2, LIGHTGRAY); 54 | DrawRectangle(startButtonPos.x, startButtonPos.y, BUTTON_WIDTH, BUTTON_HEIGHT, ButtonFocused ? DARKGRAY : LIGHTGRAY); 55 | DrawRectangle(exitButtonPos.x, exitButtonPos.y, BUTTON_WIDTH, BUTTON_HEIGHT, !ButtonFocused ? DARKGRAY : LIGHTGRAY); 56 | DrawText("Start", startButtonPos.x + BUTTON_WIDTH / 4, startButtonPos.y + BUTTON_HEIGHT / 4, 20, BLACK); 57 | DrawText("Exit", exitButtonPos.x + BUTTON_WIDTH / 4, exitButtonPos.y + BUTTON_HEIGHT / 4, 20, BLACK); 58 | EndDrawing(); 59 | } 60 | CloseWindow(); 61 | UnloadSound(fxButtonHover); 62 | UnloadSound(fxButton); 63 | return 0; 64 | } 65 | 66 | int Boot() 67 | { 68 | int framesCounter = 0; 69 | int lettersCount = 0; 70 | int state = 0; 71 | float alpha = 1.0f; 72 | int topSideRecWidth = 16; 73 | int leftSideRecHeight = 16; 74 | int bottomSideRecWidth = 16; 75 | int rightSideRecHeight = 16; 76 | Sound BootSfx = LoadSound("./res/audio/Boot.wav"); 77 | PlaySound(BootSfx); 78 | while(!WindowShouldClose()) { 79 | int logoPositionX = GetScreenWidth()/2 - 128; 80 | int logoPositionY = GetScreenHeight()/2 - 128; 81 | float deltaTime = GetFrameTime(); 82 | if (state == 0) 83 | { 84 | framesCounter += deltaTime; 85 | if (framesCounter == 1 / 120) 86 | { 87 | state = 1; 88 | framesCounter = 0; 89 | } 90 | } 91 | else if (state == 1) 92 | { 93 | topSideRecWidth += 4; 94 | leftSideRecHeight += 4; 95 | if (topSideRecWidth == 256) state = 2; 96 | } 97 | else if (state == 2) 98 | { 99 | bottomSideRecWidth += 4; 100 | rightSideRecHeight += 4; 101 | if (bottomSideRecWidth == 256) state = 3; 102 | } 103 | else if (state == 3) 104 | { 105 | framesCounter += deltaTime; 106 | if (framesCounter == 1 / 12) 107 | { 108 | lettersCount++; 109 | framesCounter = 0; 110 | } 111 | if (lettersCount >= 10) 112 | { 113 | alpha -= 0.02f; 114 | if (alpha <= 0.0f) 115 | { 116 | alpha = 0.0f; 117 | UnloadSound(BootSfx); 118 | return 0; 119 | } 120 | } 121 | } 122 | BeginDrawing(); 123 | ClearBackground(BLACK); 124 | if (state == 0) 125 | { 126 | if ((framesCounter/15)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, WHITE); 127 | } 128 | else if (state == 1) 129 | { 130 | DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, WHITE); 131 | DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, WHITE); 132 | } 133 | else if (state == 2) 134 | { 135 | DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, WHITE); 136 | DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, WHITE); 137 | DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, WHITE); 138 | DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, WHITE); 139 | } 140 | else if (state == 3) 141 | { 142 | DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(WHITE, alpha)); 143 | DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(WHITE, alpha)); 144 | DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(WHITE, alpha)); 145 | DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(WHITE, alpha)); 146 | DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(BLACK, alpha)); 147 | DrawText(TextSubtext("raylib", 0, lettersCount), GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(WHITE, alpha)); 148 | } 149 | EndDrawing(); 150 | } 151 | CloseWindow(); 152 | UnloadSound(BootSfx); 153 | return 0; 154 | } 155 | 156 | #endif // MENU_H -------------------------------------------------------------------------------- /src/player.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYER_H 2 | #define PLAYER_H 3 | 4 | #include "raylib.h" 5 | #include "raymath.h" 6 | #include 7 | 8 | const char *animPaths[] = { 9 | "./res/sprites/player/idle.gif", 10 | "./res/sprites/player/idle.gif", 11 | "./res/sprites/player/idle-down.gif", 12 | "./res/sprites/player/idle-up.gif", 13 | "./res/sprites/player/move.gif", 14 | "./res/sprites/player/move.gif", 15 | "./res/sprites/player/move-down.gif", 16 | "./res/sprites/player/move-up.gif" 17 | }; 18 | 19 | typedef enum { 20 | ANIM_IDLE_LEFT, 21 | ANIM_IDLE_RIGHT, 22 | ANIM_IDLE_DOWN, 23 | ANIM_IDLE_UP, 24 | ANIM_MOVE_LEFT, 25 | ANIM_MOVE_RIGHT, 26 | ANIM_MOVE_DOWN, 27 | ANIM_MOVE_UP 28 | } Animation; 29 | 30 | const char *animNames[] = { 31 | "IDLE_LEFT", 32 | "IDLE_RIGHT", 33 | "IDLE_DOWN", 34 | "IDLE_UP", 35 | "MOVE_LEFT", 36 | "MOVE_RIGHT", 37 | "MOVE_DOWN", 38 | "MOVE_UP" 39 | }; 40 | 41 | int animFrames; 42 | unsigned int nextFrameDataOffset; 43 | int currentAnimFrame = 0; 44 | float frameCounter = 0.0f; 45 | float frameDuration = 0.25f; 46 | Vector2 PlayerPosition = (Vector2){ 0, 0 }; 47 | Animation currentAnim = ANIM_IDLE_LEFT; 48 | Animation lastIdleAnim = ANIM_IDLE_LEFT; 49 | Animation prevAnim = ANIM_IDLE_LEFT; 50 | bool isFlipped = false; 51 | float speed = 135.0f; 52 | float speedmult = 1.55f; 53 | float rumblespeed = 0.0f; 54 | float maxrumblespeed = 1.5f; 55 | float rotation = 0.0f; 56 | Image imPlayer; 57 | Texture2D texPlayer; 58 | float deltaTime; 59 | 60 | void LoadPlayerAnimation() { 61 | if (imPlayer.data) UnloadImage(imPlayer); 62 | if (texPlayer.id) UnloadTexture(texPlayer); 63 | imPlayer = LoadImageAnim(animPaths[currentAnim], &animFrames); 64 | texPlayer = LoadTextureFromImage(imPlayer); 65 | } 66 | 67 | void Rumble() { 68 | if ((speed + rumblespeed) >= 500.0f) { 69 | rumblespeed += (float)rand() / (float)(RAND_MAX / (maxrumblespeed)); 70 | rumblespeed -= 0.5f; 71 | } else { 72 | rumblespeed += (float)rand() / (float)(RAND_MAX / (maxrumblespeed)); 73 | } 74 | } 75 | 76 | void Player() { 77 | Rectangle sourceRec = (Rectangle){ 78 | isFlipped ? texPlayer.width : 0.0f, 79 | 0.0f, 80 | isFlipped ? -texPlayer.width : texPlayer.width, 81 | texPlayer.height 82 | }; 83 | Rectangle destRec = (Rectangle){ 84 | PlayerPosition.x , 85 | PlayerPosition.y , 86 | texPlayer.width * 4.0f, 87 | texPlayer.height * 4.0f 88 | }; 89 | Vector2 origin = { destRec.width * 0.5f, destRec.height * 0.5f }; 90 | DrawTexturePro(texPlayer, sourceRec, destRec, origin, rotation, WHITE); 91 | } 92 | 93 | void PlayerLoop() { 94 | deltaTime = GetFrameTime(); 95 | frameCounter += deltaTime; 96 | if (frameCounter >= frameDuration) { 97 | currentAnimFrame++; 98 | if (currentAnimFrame >= animFrames) currentAnimFrame = 0; 99 | nextFrameDataOffset = imPlayer.width * imPlayer.height * 4 * currentAnimFrame; 100 | UpdateTexture(texPlayer, ((unsigned char *)imPlayer.data) + nextFrameDataOffset); 101 | frameCounter = 0.0f; 102 | } 103 | prevAnim = currentAnim; 104 | // Horizontal Movement 105 | if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { 106 | if ((IsKeyDown(KEY_LEFT_SHIFT))&&(prevAnim == ANIM_MOVE_UP||prevAnim == ANIM_MOVE_DOWN)&&(IsKeyDown(KEY_UP)||IsKeyDown(KEY_W)||IsKeyDown(KEY_DOWN)||IsKeyDown(KEY_S))) {Rumble();} 107 | PlayerPosition.x += (speed + rumblespeed) * deltaTime; 108 | currentAnim = ANIM_MOVE_RIGHT; 109 | lastIdleAnim = ANIM_IDLE_RIGHT; 110 | isFlipped = false; 111 | } else if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { 112 | if ((IsKeyDown(KEY_LEFT_SHIFT))&&(prevAnim == ANIM_MOVE_UP||prevAnim == ANIM_MOVE_DOWN)&&(IsKeyDown(KEY_UP)||IsKeyDown(KEY_W)||IsKeyDown(KEY_DOWN)||IsKeyDown(KEY_S))) {Rumble();} 113 | PlayerPosition.x -= (speed + rumblespeed) * deltaTime; 114 | currentAnim = ANIM_MOVE_LEFT; 115 | lastIdleAnim = ANIM_IDLE_LEFT; 116 | isFlipped = true; 117 | } else if (IsKeyReleased(KEY_RIGHT) || IsKeyReleased(KEY_D) || IsKeyReleased(KEY_LEFT) || IsKeyReleased(KEY_A)) { 118 | rumblespeed = 0.0f; 119 | currentAnim = lastIdleAnim; 120 | } 121 | // Vertical Movement 122 | if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) { 123 | if ((IsKeyDown(KEY_LEFT_SHIFT))&&(prevAnim == ANIM_MOVE_LEFT||prevAnim == ANIM_MOVE_RIGHT)&&(IsKeyPressed(KEY_RIGHT)||IsKeyPressed(KEY_D)||IsKeyPressed(KEY_LEFT)||IsKeyPressed(KEY_A))) {Rumble();} 124 | PlayerPosition.y -= (speed + rumblespeed) * deltaTime; 125 | currentAnim = ANIM_MOVE_UP; 126 | lastIdleAnim = ANIM_IDLE_UP; 127 | } else if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { 128 | if ((IsKeyDown(KEY_LEFT_SHIFT))&&(prevAnim == ANIM_MOVE_LEFT||prevAnim == ANIM_MOVE_RIGHT)&&(IsKeyPressed(KEY_RIGHT)||IsKeyPressed(KEY_D)||IsKeyPressed(KEY_LEFT)||IsKeyPressed(KEY_A))) {Rumble();} 129 | PlayerPosition.y += (speed + rumblespeed) * deltaTime; 130 | currentAnim = ANIM_MOVE_DOWN; 131 | lastIdleAnim = ANIM_IDLE_DOWN; 132 | } else if (IsKeyReleased(KEY_UP) || IsKeyReleased(KEY_W) || IsKeyReleased(KEY_DOWN) || IsKeyReleased(KEY_S)) { 133 | rumblespeed = 0.0f; 134 | currentAnim = lastIdleAnim; 135 | } 136 | // Animation 137 | if (prevAnim != currentAnim) { 138 | LoadPlayerAnimation(); 139 | currentAnimFrame = 0; 140 | frameCounter = 0.0f; 141 | } 142 | // Diagonal Movement 143 | float siderotation = 10.0f; 144 | const float targetRotation = 145 | ((IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) && (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D))) ? siderotation : 146 | ((IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) && (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A))) ? -siderotation : 147 | ((IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) && (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D))) ? -siderotation : 148 | ((IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) && (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A))) ? siderotation : 149 | 0.0f ; 150 | // Interpolating rotation 151 | const float rotationSpeed = 180.0f; 152 | const float maxRotationChange = rotationSpeed * deltaTime; 153 | if (targetRotation > rotation) { 154 | rotation = fmin(rotation + maxRotationChange, targetRotation); 155 | } else if (targetRotation < rotation) { 156 | rotation = fmax(rotation - maxRotationChange, targetRotation); 157 | } 158 | // Diagonal Rumble fix 159 | if( ((IsKeyDown(KEY_UP)||IsKeyDown(KEY_W))||(IsKeyDown(KEY_DOWN)||IsKeyDown(KEY_S))) && ((IsKeyDown(KEY_RIGHT)||IsKeyDown(KEY_D)||(IsKeyDown(KEY_LEFT)||IsKeyDown(KEY_A))))){ 160 | rumblespeed -= 0.65f; 161 | } 162 | // Sprint 163 | if (IsKeyPressed(KEY_LEFT_SHIFT)) { 164 | speed = (speed + rumblespeed) * speedmult; 165 | frameDuration = frameDuration / 2; 166 | } else if (IsKeyReleased(KEY_LEFT_SHIFT)) { 167 | speed = (speed + rumblespeed) / speedmult; 168 | frameDuration = frameDuration * 2; 169 | rumblespeed = 0.0f; 170 | } 171 | } 172 | 173 | void PlayerInit() { 174 | Vector2 PlayerPosition = (Vector2){ GetScreenWidth()/2.0f, GetScreenHeight()/2.0f }; 175 | LoadPlayerAnimation(); 176 | } 177 | 178 | void UnloadPlayer() { 179 | UnloadTexture(texPlayer); 180 | UnloadImage(imPlayer); 181 | } 182 | 183 | void PlayerInfo() { 184 | DrawText(TextFormat("X: %.0f, Y: %.0f", PlayerPosition.x, PlayerPosition.y),10, GetScreenHeight() - 20, 10, WHITE); 185 | DrawText(TextFormat("Anim State: %s", animNames[currentAnim]),10, GetScreenHeight() - 40, 10, WHITE); 186 | DrawText(TextFormat("Speed: %.0f", speed + rumblespeed),10, GetScreenHeight() - 60 , 10, WHITE); 187 | DrawFPS(10, 10); 188 | } 189 | 190 | #endif // PLAYER_H --------------------------------------------------------------------------------