commit c9500a5548435195f796c87acfb95a0bf886820c Author: Alexander Klein Date: Sat May 6 18:33:58 2023 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d51cc0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +*.exe \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f6de554 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,60 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/KleiaxSnake", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": false + } + ], + "windows": { + "miDebuggerPath": "C:/raylib/w64devkit/bin/gdb.exe", + }, + "osx": { + "MIMode": "lldb" + }, + "linux": { + "miDebuggerPath": "/usr/bin/gdb", + }, + "preLaunchTask": "build debug" + }, + { + "name": "Run", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "program": "${workspaceFolder}/${fileBasenameNoExtension}", + "MIMode": "gdb", + "windows": { + "program": "${workspaceFolder}/${fileBasenameNoExtension}.exe", + "miDebuggerPath": "C:/raylib/w64devkit/bin/gdb.exe" + }, + "osx": { + "MIMode": "lldb" + }, + "linux": { + "miDebuggerPath": "/usr/bin/gdb" + }, + "preLaunchTask": "build release", + } + ] + } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e98318a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/*.o": true, + "**/*.exe": true, + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..597b44f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,58 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "build debug", + "type": "process", + "command": "make", + "args": [ + ], + "windows": { + "command": "mingw32-make.exe", + "args": [ + "RAYLIB_PATH=C:/raylib/raylib", + // "OBJS=${fileBasenameNoExtension}.cpp", + "BUILD_MODE=DEBUG" + ], + }, + "group": { + "kind": "build", + "isDefault": true + }, + "problemMatcher": [ + "$g++" + ] + }, + { + "label": "build release", + "type": "process", + "command": "make", + "args": [ + "PLATFORM=PLATFORM_DESKTOP", + // "PROJECT_NAME=${fileBasenameNoExtension}", + "OBJS=${fileBasenameNoExtension}.cpp" + ], + "windows": { + "command": "mingw32-make.exe", + "args": [ + "RAYLIB_PATH=C:/raylib/raylib", + "PROJECT_NAME=${fileBasenameNoExtension}", + "OBJS=${fileBasenameNoExtension}.cpp" + ], + }, + "osx": { + "args": [ + "RAYLIB_PATH=/raylib", + "PROJECT_NAME=${fileBasenameNoExtension}", + "OBJS=${fileBasenameNoExtension}.c++" + ], + }, + "group": "build", + "problemMatcher": [ + "$g++" + ] + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..34f514c --- /dev/null +++ b/Makefile @@ -0,0 +1,113 @@ +.PHONY: all clean + +# Define required raylib variables +PROJECT_NAME ?= KleiaxSnake +RAYLIB_VERSION ?= 4.2.0 +RAYLIB_PATH ?= ..\.. + +# Define compiler path on Windows +COMPILER_PATH ?= C:/raylib/w64devkit/bin + +PLATFORM ?= PLATFORM_DESKTOP + +DESTDIR ?= /usr/local +RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib +RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include + +# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) +RAYLIB_LIBTYPE ?= STATIC + +# Build mode for project: DEBUG or RELEASE +BUILD_MODE ?= DEBUG + +ifeq ($(OS),Windows_NT) + PLATFORM_OS=WINDOWS + export PATH := $(COMPILER_PATH):$(PATH) +endif + +RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src +EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) + +# Define default C compiler: gcc +# NOTE: define g++ compiler if using C++ +CC = g++ + +# Define default make program: Mingw32-make +MAKE = mingw32-make + +# Define compiler flags: +# -O0 defines optimization level (no optimization, better for debugging) +# -O1 defines optimization level +# -g include debug information on compilation +# -s strip unnecessary data from build -> do not use in debug builds +# -Wall turns on most, but not all, compiler warnings +# -std=c99 defines C language mode (standard C from 1999 revision) +# -std=gnu99 defines C language mode (GNU C from 1999 revision) +# -Wno-missing-braces ignore invalid warning (GCC bug 53119) +# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec +CFLAGS += -Wall -Wno-missing-braces + +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS += -g -O0 +else + CFLAGS += -s -O1 +endif + + +# Define include paths for required headers +# NOTE: Several external required libraries (stb and others) +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external +INCLUDE_PATHS += -I./include +# INCLUDE_PATHS += -I./src + +# Define library paths containing required libs. +LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src + +# Define any libraries required on linking +# if you want to link libraries (libname.so or libname.a), use the -lname +ifeq ($(PLATFORM_OS),WINDOWS) + # Libraries for Windows desktop compilation + # NOTE: WinMM library required to set high-res timer resolution + LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm +endif + +# Define a recursive wildcard function +rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) + +# Define all source files required +SRC_DIR = src +OBJ_DIR = obj + +# Define all object files from source files +# SRC = $(call rwildcard, *.c, *.h) +SRC = $(call rwildcard, *.cpp, *.h) +# OBJS = $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o) +OBJS ?= main.cpp +OBJS += src/Game.cpp +OBJS += src/Board.cpp +OBJS += src/raylibCpp.cpp +OBJS += src/Snake.cpp + +MAKEFILE_PARAMS = $(PROJECT_NAME) + + +all: + $(MAKE) $(MAKEFILE_PARAMS) + +# Project target defined by PROJECT_NAME +$(PROJECT_NAME): $(OBJS) + $(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + +# Compile source files +# NOTE: This pattern will compile every module defined on $(OBJS) +#%.o: %.c +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) + +# Clean everything +clean: + ifeq ($(PLATFORM_OS),WINDOWS) + del *.o *.exe /s + endif + @echo Cleaning done + diff --git a/include/Board.h b/include/Board.h new file mode 100644 index 0000000..873743e --- /dev/null +++ b/include/Board.h @@ -0,0 +1,21 @@ +#pragma once + +#include "raylibCpp.h" +#include +#include "Vec2.h" +#include "Settings.h" + +class Board { + public: + Board(Vec2 screenPos, Vec2 widthHeight, int padding); + void DrawBorder() const; + void Draw() const; + int GetWidth() const; + int GetHeight() const; + private: + int width; + int height; + const int padding; + Vec2 size; + Vec2 screenPos; +}; \ No newline at end of file diff --git a/include/Game.h b/include/Game.h new file mode 100644 index 0000000..cbc86be --- /dev/null +++ b/include/Game.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include "Board.h" +#include "Snake.h" + +class Game { + public: + Game(int width, int height, int fps, std::string title); + Game(const Game& other) = delete; + Game& operator=(const Game& other) = delete; + ~Game() noexcept; + bool GameShouldClose() const; + void Tick(); + private: + void Update(); + void Draw(); + + Board board; + Snake snake; +}; \ No newline at end of file diff --git a/include/Settings.h b/include/Settings.h new file mode 100644 index 0000000..7e46cea --- /dev/null +++ b/include/Settings.h @@ -0,0 +1,15 @@ +#pragma once +#include "Vec2.h" +namespace settings +{ + //Board settings + inline constexpr Vec2 gridSize{30, 15}; + inline constexpr Vec2 gridPos{50, 50}; + inline constexpr int gridCellSize = 30; + inline constexpr int gridInnerPadding = 2; + inline constexpr int gridBorderWidth = 15; + + //Window settings + inline constexpr int fps = 60; + +} \ No newline at end of file diff --git a/include/Snake.h b/include/Snake.h new file mode 100644 index 0000000..aeb9325 --- /dev/null +++ b/include/Snake.h @@ -0,0 +1,72 @@ +#pragma once + +#include "raylibCpp.h" +#include +#include +#include +#include "Vec2.h" +#include "Settings.h" + +class Snake { + public: + enum Direction { + Up, + Down, + Left, + Right, + None + }; + + private: + class Body { + public: + Body(Vec2 pos); + + void draw(Color color = WHITE) const; + void move(Vec2 pos) { this->pos = pos; }; + Vec2 getPos() const { return this->pos; } + static void setSize(Vec2 size) { Body::size = size; } + + private: + Vec2 pos; + static Vec2 size; + Snake::Direction nextPart; + }; + + class Food { + public: + Food(); + + void draw() const; + void newPosition(); + Vec2 getPosition() { return this->pos; } + + private: + Vec2 pos; + Vec2 size; + }; + + public: + Snake(); + + void update(); + void draw() const; + + void setDirection(Direction dir); + private: + void move(); + void eat(); + + Direction dir = Direction::None; + Food food; + + bool hasEaten = false; + bool hasBitten = false; + + int score = 0; + + double lastMoveTime = 0; + double moveDelay = 0.15; + + std::list bodyList; +}; \ No newline at end of file diff --git a/include/Vec2.h b/include/Vec2.h new file mode 100644 index 0000000..8c06c46 --- /dev/null +++ b/include/Vec2.h @@ -0,0 +1,66 @@ +#pragma once + +template +class Vec2 +{ +public: + Vec2() = default; + constexpr Vec2(T x, T y) + : + x(x), + y(y) + {} + constexpr T GetX() const {return x;}; + constexpr T GetY() const {return y;}; + constexpr void SetX(T x_in) { x = x_in;}; + constexpr void SetY(T y_in) { y = y_in;}; +public: + constexpr bool operator==(const Vec2& rhs) const + { + return (x == rhs.x && y == rhs.y); + } + constexpr bool operator!=(const Vec2& rhs) const + { + return !(*this == rhs); + } + constexpr Vec2 operator+(const Vec2& rhs) const + { + return {x + rhs.x, y + rhs.y}; + } + constexpr Vec2 operator+(const int rhs) const + { + return {x + rhs, y + rhs}; + } + constexpr Vec2& operator+=(const Vec2& rhs) + { + return *this = *this + rhs; + } + constexpr Vec2 operator-(const Vec2& rhs) const + { + return {x - rhs.x, y - rhs.y}; + } + constexpr Vec2 operator-(const int rhs) const + { + return { x - rhs, y - rhs}; + } + constexpr Vec2& operator-=(const Vec2& rhs) + { + return *this = *this - rhs; + } + constexpr Vec2 operator*(const Vec2& rhs) const + { + return {x * rhs.x, y * rhs.y}; + } + constexpr Vec2 operator*(const int rhs) const + { + return { x * rhs, y * rhs }; + } + constexpr Vec2& operator*=(const Vec2& rhs) + { + return *this = *this * rhs; + } + +private: + T x; + T y; +}; \ No newline at end of file diff --git a/include/raylibCpp.h b/include/raylibCpp.h new file mode 100644 index 0000000..1078d86 --- /dev/null +++ b/include/raylibCpp.h @@ -0,0 +1,8 @@ +#pragma once +#include +#include "Vec2.h" +namespace raycpp +{ + void DrawRectangle(Vec2 pos, Vec2 widthHeight, Color color); + void DrawRectangleLinesEx(Vec2 pos, Vec2 widthHeight, int lineThick, Color color); +} \ No newline at end of file diff --git a/main.code-workspace b/main.code-workspace new file mode 100644 index 0000000..e041d24 --- /dev/null +++ b/main.code-workspace @@ -0,0 +1,24 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "files.associations": { + "raylib.h": "c", + "math.h": "c", + "blocks.h": "c", + "stdio.h": "c", + "*.m": "c" + }, + "cSpell.words": [ + "DARKGRAY", + "fovy", + "Kleiax", + "raycpp", + "raylib", + "RAYWHITE" + ] + } +} \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..618bc24 --- /dev/null +++ b/main.cpp @@ -0,0 +1,25 @@ +#include "Game.h" +#include "Settings.h" + +int main(void) { + int width = 2 * settings::gridPos.GetX() + + 2 * settings::gridBorderWidth + + settings::gridSize.GetX() * settings::gridCellSize + + (settings::gridSize.GetX() + 1) * settings::gridInnerPadding; + + int height = 2 * settings::gridPos.GetY() + + 2 * settings::gridBorderWidth + + settings::gridSize.GetY() * settings::gridCellSize + + (settings::gridSize.GetY() + 1) * settings::gridInnerPadding; + + Game game{width, + height, + settings::fps, + "Snake Kleiax Raylib"}; + + while (!game.GameShouldClose()) + { + game.Tick(); + } + return 0; +} \ No newline at end of file diff --git a/resources/LICENSE b/resources/LICENSE new file mode 100644 index 0000000..ebde2c5 --- /dev/null +++ b/resources/LICENSE @@ -0,0 +1 @@ +Assets license. diff --git a/src/Board.cpp b/src/Board.cpp new file mode 100644 index 0000000..ce1542a --- /dev/null +++ b/src/Board.cpp @@ -0,0 +1,41 @@ +#include "Board.h" +#include + + +Board::Board(Vec2 screenPos, Vec2 widthHeight, int padding) : + screenPos(screenPos), + size(widthHeight), + padding(padding) { + this->width = 2 * settings::gridBorderWidth + + settings::gridSize.GetX() * settings::gridCellSize + + (settings::gridSize.GetX() + 1) * settings::gridInnerPadding; + + this->height = 2 * settings::gridBorderWidth + + settings::gridSize.GetY() * settings::gridCellSize + + (settings::gridSize.GetY() + 1) * settings::gridInnerPadding; + + assert(width > 0 && height > 0); //If assertion triggers : The width or height is smaller than 1 +} + +void Board::DrawBorder() const +{ + raycpp::DrawRectangleLinesEx(screenPos, + Vec2{width,height}, + settings::gridBorderWidth, + WHITE); +} + +void Board::Draw() const +{ + DrawBorder(); +} + +int Board::GetWidth() const +{ + return width; +} + +int Board::GetHeight() const +{ + return height; +} diff --git a/src/Game.cpp b/src/Game.cpp new file mode 100644 index 0000000..d7d8ea6 --- /dev/null +++ b/src/Game.cpp @@ -0,0 +1,58 @@ +#include +#include "Game.h" +#include "raylibCpp.h" +#include "Settings.h" +Game::Game(int width, int height, int fps, std::string title) : + board(settings::gridPos, + settings::gridSize, + settings::gridInnerPadding) +{ + assert(!GetWindowHandle()); //If assertion triggers : Window is already opened + SetTargetFPS(fps); + InitWindow(width, height, title.c_str()); +} + +Game::~Game() noexcept +{ + assert(GetWindowHandle()); //If assertion triggers : Window is already closed + CloseWindow(); +} + +bool Game::GameShouldClose() const +{ + return WindowShouldClose(); +} + +void Game::Tick() +{ + BeginDrawing(); + Update(); + Draw(); + EndDrawing(); +} + +void Game::Update() +{ + if (IsKeyPressed(KEY_UP)) + snake.setDirection(Snake::Direction::Up); + else if (IsKeyPressed(KEY_DOWN)) + snake.setDirection(Snake::Direction::Down); + else if (IsKeyPressed(KEY_LEFT)) + snake.setDirection(Snake::Direction::Left); + else if (IsKeyPressed(KEY_RIGHT)) + snake.setDirection(Snake::Direction::Right); + else if (IsKeyPressed(KEY_SPACE)) + snake.setDirection(Snake::Direction::None); + + snake.update(); +} + +void Game::Draw() +{ + ClearBackground(BLACK); + board.Draw(); + snake.draw(); +} + + + diff --git a/src/Snake.cpp b/src/Snake.cpp new file mode 100644 index 0000000..d3aec6d --- /dev/null +++ b/src/Snake.cpp @@ -0,0 +1,166 @@ +#include "Snake.h" + +Vec2 Snake::Body::size; + +Snake::Body::Body(Vec2 pos) { + this->pos = pos; +} + +void Snake::Body::draw(Color color) const{ + int offsetX = settings::gridPos.GetX() + settings::gridBorderWidth + settings::gridInnerPadding; + int offsetY = settings::gridPos.GetY() + settings::gridBorderWidth + settings::gridInnerPadding; + + Vec2 pixelPos; + pixelPos.SetX(offsetX + this->pos.GetX() * (settings::gridCellSize + settings::gridInnerPadding)); + pixelPos.SetY(offsetY + this->pos.GetY() * (settings::gridCellSize + settings::gridInnerPadding)); + raycpp::DrawRectangle(pixelPos, this->size, color); +} + +Snake::Food::Food() { + this->newPosition(); + this->size.SetX(settings::gridCellSize); + this->size.SetY(settings::gridCellSize); +} + +void Snake::Food::newPosition() { + int x = GetRandomValue(0, settings::gridSize.GetX() - 1); + int y = GetRandomValue(0, settings::gridSize.GetY() - 1); + + this->pos.SetX(x); + this->pos.SetY(y); +} + +void Snake::Food::draw() const { + int offsetX = settings::gridPos.GetX() + settings::gridBorderWidth + settings::gridInnerPadding; + int offsetY = settings::gridPos.GetY() + settings::gridBorderWidth + settings::gridInnerPadding; + + Vec2 pixelPos; + pixelPos.SetX(offsetX + this->pos.GetX() * (settings::gridCellSize + settings::gridInnerPadding)); + pixelPos.SetY(offsetY + this->pos.GetY() * (settings::gridCellSize + settings::gridInnerPadding)); + raycpp::DrawRectangle(pixelPos, this->size, RED); +} + +Snake::Snake() { + Body::setSize(Vec2{settings::gridCellSize, settings::gridCellSize}); + + this->bodyList.push_back(Body{Vec2{5, 5}}); + this->bodyList.push_back(Body{Vec2{5, 6}}); + this->bodyList.push_back(Body{Vec2{5, 7}}); +} + +void Snake::update() { + if (GetTime() - this->lastMoveTime < this->moveDelay || this->hasBitten) + return; + this->lastMoveTime = GetTime(); + + this->move(); + + Vec2 head = (*this->bodyList.cbegin()).getPos(); + if (head == this->food.getPosition()) + this->eat(); + + bool firstSkip = true; + for (const Body & body : this->bodyList) { + if (firstSkip) { + firstSkip = false; + continue; + } + if (head == body.getPos()) + this->hasBitten = true; + } +} + +void Snake::draw() const { + for (const Body & body : this->bodyList) + body.draw(); + (*this->bodyList.cbegin()).draw(GREEN); + this->food.draw(); + + std::string scoreString; + scoreString += "Score: "; + scoreString += std::to_string(this->score); + DrawText(scoreString.c_str(), 10, 10, 30, WHITE); + + if (this->hasBitten) + DrawText("Game over!", 10, 70, 50, BLUE); +} + +void Snake::setDirection(Direction dir) { + if (this->dir == Direction::Up && dir == Direction::Down) + return; + + if (this->dir == Direction::Down && dir == Direction::Up) + return; + + if (this->dir == Direction::Left && dir == Direction::Right) + return; + + if (this->dir == Direction::Right && dir == Direction::Left) + return; + + this->dir = dir; +} + +void Snake::move() { + if (this->dir == Direction::None) + return; + + Vec2 head = (*this->bodyList.cbegin()).getPos(); + + if (this->hasEaten) + this->hasEaten = false; + else + this->bodyList.pop_back(); + + switch (this->dir) + { + case Direction::Up: + head.SetY(head.GetY() - 1); + break; + + case Direction::Down: + head.SetY(head.GetY() + 1); + break; + + case Direction::Left: + head.SetX(head.GetX() - 1); + break; + + case Direction::Right: + head.SetX(head.GetX() + 1); + break; + + default: + break; + } + + if (head.GetX() >= settings::gridSize.GetX()) + head.SetX(0); + else if (head.GetX() < 0) + head.SetX(settings::gridSize.GetX() - 1); + + if (head.GetY() >= settings::gridSize.GetY()) + head.SetY(0); + else if (head.GetY() < 0) + head.SetY(settings::gridSize.GetY() - 1); + + this->bodyList.push_front(Snake::Body(head)); +} + +void Snake::eat() { + this->hasEaten = true; + this->food.newPosition(); + this->score++; + + bool newFoodPlaceFound = false; + while (!newFoodPlaceFound) { + this->food.newPosition(); + newFoodPlaceFound = true; + for (const Body & body : this->bodyList) + if (this->food.getPosition() == body.getPos()) { + newFoodPlaceFound = false; + break; + } + } + +} \ No newline at end of file diff --git a/src/raylibCpp.cpp b/src/raylibCpp.cpp new file mode 100644 index 0000000..92d3734 --- /dev/null +++ b/src/raylibCpp.cpp @@ -0,0 +1,16 @@ +#include "raylibCpp.h" +#include +void raycpp::DrawRectangle(Vec2 pos, Vec2 widthHeight, Color color) +{ + assert(pos.GetX() >= 0 && pos.GetY() >= 0 && + pos.GetX() < GetScreenWidth() && pos.GetY() < GetScreenHeight()); //If assertion triggers : Trying to draw outisde of the screen + DrawRectangle(pos.GetX(),pos.GetY(),widthHeight.GetX(),widthHeight.GetY(),color); +} + +void raycpp::DrawRectangleLinesEx(Vec2 pos, Vec2 widthHeight, int lineThick, Color color) +{ + assert(pos.GetX() >= 0 && pos.GetY() >= 0 && + pos.GetX() < GetScreenWidth() && pos.GetY() < GetScreenHeight()); //If assertion triggers : Trying to draw outisde of the screen + assert(lineThick > 0); //If assertion triggers : line thickness is less than 1 + DrawRectangleLinesEx({(float)pos.GetX(),(float)pos.GetY(), (float)widthHeight.GetX(), (float)widthHeight.GetY()}, (float)lineThick, color); +}