Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • et2-stoker/assignment2020resit
1 result
Show changes
Commits on Source (28)
Showing with 1804 additions and 0 deletions
*.exe
*.obj
a.out
html
latex
*.o
build
\ No newline at end of file
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${default}",
"${workspaceFolder}/include",
"${workspaceFolder}/windows/include",
"${workspaceFolder}/windows/include/SDL2",
"${workspaceFolder}/assignment"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}
\ No newline at end of file
{
"files.associations": {
"*.ipp": "cpp",
"iostream": "cpp"
}
}
\ No newline at end of file
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "Make",
"command": "/usr/bin/make",
"args": [
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": "build"
},
{
"type": "shell",
"label": "C/C++: cl.exe build active file",
"command": "cl.exe",
"args": [
"/std:c++17",
"/Zi",
"/EHsc",
"/Fe:",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"${file}"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$msCompile"
],
"group": "build"
}
]
}
\ No newline at end of file
This diff is collapsed.
CC = clang++
LD = clang++
CPPFLAGS = -std=c++17 -I./osx/include/ -I./osx/include/SDL2/ -I./include
CFLAGS = -I./osx/include/ -I./osx/include/SDL2/ -I./include
LDFLAGS = -L./osx/lib/ -lSDL2 -lSDL2_ttf -lSDL2_image -lfreetype -lpng -lwebp -ltiff -ljpeg -lbz2 -lz -framework OpenGL
ROOTDIR = ./
LIBDIR=S(ROOTDIR)/osx/lib
CP = cp
ECHO = echo
BUILD_DIR = build
C_SOURCES = src/SDL_FontCache.c
CPP_SOURCES = src/app.cpp src/context.cpp
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
vpath %.cpp examples
vpath %.cpp assignment
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
$(ECHO) compiling $<
$(CC) -c $(CPPFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(ECHO) compiling $<
clang -c $(CFLAGS) $< -o $@
all: $(BUILD_DIR)/splat $(BUILD_DIR)/shapes $(BUILD_DIR)/sprite $(BUILD_DIR)/assignment
$(BUILD_DIR)/splat: $(OBJECTS) $(BUILD_DIR)/splat.o Makefile
$(ECHO) linking $<
$(CC) -L./osx/lib/ -lSDL2 -lSDL2_ttf -lSDL2_image -lfreetype -lpng -lwebp -ltiff -ljpeg -lbz2 -lz -framework OpenGL -o $@ $(OBJECTS) build/splat.o
install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib ./osx/runtime/libSDL2-2.0.0.dylib $(BUILD_DIR)/splat
$(ECHO) success
$(BUILD_DIR)/shapes: $(OBJECTS) $(BUILD_DIR)/shapes.o Makefile
$(ECHO) linking $<
$(CC) -L./osx/lib/ -lSDL2 -lSDL2_ttf -lSDL2_image -lfreetype -lpng -lwebp -ltiff -ljpeg -lbz2 -lz -framework OpenGL -o $@ $(OBJECTS) build/shapes.o
install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib ./osx/runtime/libSDL2-2.0.0.dylib $(BUILD_DIR)/shapes
$(ECHO) success
$(BUILD_DIR)/sprite: $(OBJECTS) $(BUILD_DIR)/sprite.o Makefile
$(ECHO) linking $<
$(CC) -L./osx/lib/ -lSDL2 -lSDL2_ttf -lSDL2_image -lfreetype -lpng -lwebp -ltiff -ljpeg -lbz2 -lz -framework OpenGL -o $@ $(OBJECTS) build/sprite.o
install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib ./osx/runtime/libSDL2-2.0.0.dylib $(BUILD_DIR)/sprite
$(ECHO) success
$(BUILD_DIR)/assignment: $(OBJECTS) $(BUILD_DIR)/assignment.o Makefile
$(ECHO) linking $<
$(CC) -L./osx/lib/ -lSDL2 -lSDL2_ttf -lSDL2_image -lfreetype -lpng -lwebp -ltiff -ljpeg -lbz2 -lz -framework OpenGL -o $@ $(OBJECTS) build/assignment.o
install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib ./osx/runtime/libSDL2-2.0.0.dylib $(BUILD_DIR)/assignment
$(ECHO) success
#######################################
# clean up
#######################################
clean:
-rm -fR $(BUILD_DIR)/assignment $(BUILD_DIR)/sprite $(BUILD_DIR)/shapes $(BUILD_DIR)/splat $(BUILD_DIR)/*.o
#######################################
# dependencies
#######################################
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
.PHONY: clean all
\ No newline at end of file
```UFCFGL-30-1 Programming in c++```
# Assignment
Fork and clone the repo [https://gitlab.uwe.ac.uk/br-gaster/assignment_2020](https://gitlab.uwe.ac.uk/br-gaster/assignment_2020).
Now follow the instructions below.
As normal all work should be peformed within your forked repo and sumitted to Gitlab.uwe.ac.uk.
## Introduction
A 2D interaction and drawing API is provided, which includes the following functionality:
- Keyboard input
- Mouse input
- Drawing of 2D shapes
- A Pixel buffer API
- Display images
- Display text
Some possible applications:
- [Tic-Tac-Toc](https://playtictactoe.org/)
- A clone of the game [2048](https://play2048.co/)
- A clone of the game Space Invaders
- The website ["I Need Practice Programming": 49 Ideas for Game Clones to Code ](https://inventwithpython.com/blog/2012/02/20/i-need-practice-programming-49-ideas-for-game-clones-to-code/) has loads of great options.
- A image editor, with the ability to save and restore images, etc.
A base applicaition is given in:
- **assignment/assignment.cpp**
and you should use this to being your assignment. Details of the framework are given in the API section below.
You can feel free to make it as complex as you choose. The marking scheme is designed to enable different levels of ability, with the base being get something up and running and build on it from there. However, to get a high mark it will need to have a level of complexity, that is beyond just handing input and display things no the screen.
### The marking scheme
- Implement a simple example program using the framework provided : 30 marks
- Your program supports interaction and state, e.g. allows the user to draw sprites, these sprites, can be saved, and restored: 20 Marks
- Your programs demostrates a complex application, e.g. it might be 2D game, such as 2048 or a simple Space Invaders: 20 Marks
- Your program is well structured, using multiple include files, and is documented, including source comments and a readme.md: 30 Marks
## Example applications
Three examples are provided as source to give you something to build upon and that demostrate different capabilities:
- *examples/splat.cpp*
- *examples/sprite.cpp*
- *examples/sprite.cpp*
See the sections on Windows and OS X for how to build these examples.
### Splat
![Splat](assets/splat.jpg)
Uses a framebuffer object to draw random pixels to the screen.
### Sprite
The beginnings of sprite editor. It opens with a window
display a single white sprite:
![Sprite](assets/sprite1.jpg)
Pressing 2 will change to the sprite editor, where
you can select from a colour palate on the bottom left,
and then draw in the expanded sprite in the middle:
![Sprite](assets/sprite2.jpg)
Pressing 1 will change back to the sprite display, and will be updated to reflect any changes. The sprite can be moved around with the arrow keys:
![Sprite](assets/sprite3.jpg)
Currently this is very basic, but it could form a starting point for:
- A more feature complete sprite editor, which could include saving, loading, sprites; tools to edit the sprite, such as fill, cut, paste; different sizes of sprites; more complex colour selection; and so on.
- Used as the basis for a simple sprite editor in a game tool kit, which combined with a map editor could provide an all in one game development platform.
### Shapes
The shapes example provides a demostration of the different features provided for drawing shapes and text:
![Shapes](assets/shapes.jpg)
## Windows
To make it slightly easier to build both the examples and the assigment itself two Bat files are provided:
- windows_build\examples.bat
- windows_build\assignment.bat
building the examples and assignment, respectively. Unlike the assignments you do not build with VS Code.
To build and run the examples, or assignment, you first change into the *windows_build* directory:
```bash
cd windows_build
```
and then run the particular bat file, e.g. to build the examples you would run:
```bash
.\examples.bat
```
and for the assigment:
```bash
.\assignments.bat
```
Run **examples.bat** builds the executables:
- **shapes.exe**
- **splat.exe**
- **sprite.exe**
and *assignment.bat* builds:
- **assigment.exe**
To run an example or the assigment, simply run the command, e.g. **./shapes.exe**,
in the same directory. (Note: it is important that you run the executables in the
**window_build** directory.)
## OS X
To make it slightly easier to build both the examples and the assigment itself a Makefile is provided:
- **Makefile**
To build and examples and assignment simple type
```bash
make
```
in the root directory. This will build the resulting
executables in the directory **build**. **build** will
contain the example executables:
```bash
./build/shapes
./build/splat
./build/sprite
```
and for the assigment:
```bash
./build/assignment
```
To run an example or the assigment, simply run the executable from the root directory, e.g. **./build/shapes**. (Note: it is important that you run the executables from the *root* directory.)
## assignment/assignment.cpp
In **assignment\assignment.cpp** you will see the definition of MyApp class as follows:
```c++
class MyApp: public uwe::App {
private:
public:
// Constructor for your application
// Window width
// Window height
// Window title
MyApp(int width, int height, std::string title);
~MyApp();
// this function is called once when the framework
// begins running. You can use it to preform setup
// of your app.
void begin() override;
// The following 2 functions are called at 60hz,
// i.e. 60 times a second. update is called before
// draw. You should update you applications state
// during update and call any drawing functions
// during draw.
void update() override;
void draw() override;
// Everytime a key is pressed this funciton is
// called
void key_pressed(uwe::Scancode scancode, bool repeat) override;
// Everytime a mouse button is pressed this
// function is called
void mouse_pressed(int x, int y, uwe::Button button) override;
// Everytime a mouse button is released this
// function is called
void mouse_released(int x, int y, uwe::Button button) override;
// Everytime the mouse is moved this function
// is called
void mouse_moved(int x, int y) override;
};
```
Default or empty implementations for all these functions are provided in **assignments/assignments.cpp**:
```c++
MyApp::MyApp(int width, int height, std::string title) {
init(width, height, title);
}
MyApp::~MyApp() {
}
void MyApp::begin() {
}
void MyApp::update() {
}
void MyApp::key_pressed(uwe::Scancode scancode, bool repeat) {
switch (scancode) {
default: {
// nothing see here
}
}
}
void MyApp::mouse_pressed(int x, int y, uwe::Button button) {
}
void MyApp::mouse_released(int x, int y, uwe::Button button) {
}
void MyApp::mouse_moved(int x, int y) {
}
void MyApp::draw() {
clear(uwe::Colour::black());
}
```
Your task is to fill these functions out to meet the requirments of your chosen application. Each of the provided examples follow this approach and give ideas of how to use different elements of the framework.
# Framework
## Colours and Rectangles
Colour can be defined with the Colour class, which
contain a red, green, and blue component, along with an alpha value, that defines the opacity.
Some predefined colours are provided.
```cpp
class Colour {
public:
uint8_t blue_;
uint8_t green_;
uint8_t red_;
uint8_t alpha_;
Colour(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
static Colour red();
static Colour green();
static Colour blue();
static Colour white();
static Colour black();
};
```
There is a utility function to make colours:
```c++
Colour make_colour(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha);
```
Lots of the drawing functions take colours as arguments.
A type of rectangles is provided:
```c++
struct Rect {
int x;
int y;
int width;
int height;
}
```
and a utility function to make rectangles is defined:
```c++
Rect make_rect(int x, int y, int width, int height);
```
## Images and Fonts
Types are provided for Images and Fonts:
```c++
Image
```
and
```c++
Font
```
respectively.
Functions for working on images are as follows:
```c++
// load a PNG file from path given
Image create_image(std::string path);
// Create an empty image of size width and height
Image create_image(int width, int height);
// Delete an existing image
void delete_image(Image image);
// get image size
void get_image_size(Image image, int *width, int *height);
// Draw an part of an image to part of the screen
void draw_image(Image image, Rect src, Rect dest);
```
Functions for working with fonts are as follows:
```c++
// Create a font from a True Type Font File (.ttf)
// For a given point size and colour.
// If you want different colours or point size, then
// a new font needs to be created.
Font create_font(std::string path, int point_size, Colour colour);
// Display a string using a given font at specified position.
void draw_font(Font font, std::string msg, float x, float y)
```
An example TTF can be found in **./assets/fonts/FreeSans.ttf**. Additional fonts can be found on the internet.
## Framebuffer
A [Framebuffer](https://en.wikipedia.org/wiki/Framebuffer) is a pixel abstraction of the window,
in which colour values can be directly written or read.
There is a single framebuffer. You can use a framebuffer for sprite style operations.
Functions for managing the framebuffer are as follows:
```c++
// Width of framebuffer, for this case it will be the
// same as window width.
int get_framebuffer_width();
// Height of framebuffer, for this case it will be the
// same as window height.
int get_framebuffer_height();
// Sets a pixel in the framebuffer to a given colour.
void set_framebuffer(int x, int y, Colour colour);
// Clears the framebuffer with a specifed colour.
void clear_framebuffer(Colour colour);
// Draw the current framebuffer to the screen/window.
void blit_framebuffer();
```
## Drawing
The following functions can be used to draw basic shapes.
```c++
// Clear the screen with to a specific colour.
void clear(Colour colour);
// Set the colour of the drawing pen
void set_draw_color(Colour colour);
// Draw rectangles with lines
void draw_rect(int x, int y, int width, int height);
void draw_rect(Rect rect);
// Draw filled rectangles
void draw_rect_fill(int x, int y, int width, int height);
void draw_rect_fill(Rect rect);
// Draw a line
void draw_line(int x1, int y1, int x2, int y2);
// Draw a point
void draw_point(int x, int y);
```
\ No newline at end of file
assets/ZX_Spectrum_character_set.png

740 B

File added
assets/shapes.jpg

168 KiB

assets/splat.jpg

3.61 MiB

assets/sprite1.jpg

73.5 KiB

assets/sprite2.jpg

146 KiB

assets/sprite3.jpg

77.5 KiB

#include <iostream>
#include <iomanip>
#include <vector>
#include <cstring>
#include <tuple>
#include <cmath>
#include <context.hpp>
#include <app.hpp>
#include <board.h>
using namespace std;
#define SIZE 3
const int width = 600;
const int height = 600;
class MyApp: public uwe::App {
public:
MyApp(int width, int height, std::string title);
~MyApp();
MyApp();
void begin() override;
void update() override;
void draw() override;
void key_pressed(uwe::Scancode scancode, bool repeat) override;
void mouse_pressed(int x, int y, uwe::Button button) override;
void mouse_released(int x, int y, uwe::Button button) override;
void mouse_moved(int x, int y) override;
// Functions to draw the X and the O relative to the grid.
void drawX(int row, int col);
void drawO(int row, int col);
private:
// Font decleration
uwe::Font font15_;
Board board;
// Boolean variables to check if the mouse has been pressed or not
bool b1c = false;
bool b1c2 = false;
// Integers for the size of the buttons used within the app
int bx = 180;
int by = 420;
int bw = 200;
int bh = 100;
int bx2 = 0;
int by2 = 0;
int bw2 = 600;
int bh2 = 600;
// Boolean values to track whose turn it is
bool playerTurn = true;
bool legalMove = false;
// Decleration of gamestate values
int state = 0;
enum GAMESTATE {MENU, BOARD, FINISH};
};
MyApp::MyApp(int width, int height, std::string title) {
init(width, height, title);
}
MyApp::~MyApp() {
}
void MyApp::begin() {
font15_ = create_font("../assets/fonts/FreeSans.ttf", 24, uwe::Colour::black());
}
void MyApp::update() {
}
void MyApp::key_pressed(uwe::Scancode scancode, bool repeat) {
switch (scancode) {
default: {
// nothing see here
}
}
}
void MyApp::mouse_pressed(int x, int y, uwe::Button button)
{
}
void MyApp::mouse_moved(int x, int y) {
}
Board::Board() { clearb(); } ;
// Function to reset all the tiles within the board back to EMPTY
void Board::clearb()
{
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
m[i][j] = EMPTY;
}
}
takenPlace = 0;
}
// Returns whether the square selected is empty
bool Board::fieldEmpty(int row, int col) const
{
if (row >= 0 && row < 3 && col >= 0 && col < 3)
return m[row][col] == EMPTY;
return false;
}
//Returns whether the square selected contains an X
bool Board::fieldX(int row, int col) const
{
if (row >= 0 && row < 3 && col >= 0 && col < 3)
return m[row][col] == PX;
return false;
}
//Returns whether the square selected contains an O
bool Board::fieldO(int row, int col) const
{
if(row >= 0 && row < 3 && col >= 0 && col < 3)
return m[row][col] == PO;
return false;
}
void MyApp::drawX(int row, int col)
{
int fieldW = width / 3;
int fieldH = height / 3;
//Top left corner to bottom right
draw_line(col * fieldW, row * fieldH + fieldH,
col * fieldW + fieldW, row * fieldH);
//Top right corner to bottom left
draw_line(col * fieldW, row * fieldH,
col * fieldW + fieldW, row * fieldH + fieldH);
}
// Function to draw the O
void MyApp::drawO(int row, int col)
{
int fieldW = width / 3;
int fieldH = height / 3;
// calculate circle center
int centerX = col * fieldW + (fieldW/2);
int centerY = row * fieldH + (fieldH/2);
int r = fieldW/2;
double step = 2*M_PI/30;
int endX = centerX + r;
int endY = centerY;
for(double angle = 0; angle < 2 * M_PI; angle += step)
{
int startX = endX;
int startY = endY;
endX = r * cos(angle) + centerX;
endY = r * sin(angle) + centerY;
draw_line(startX, startY, endX, endY);
}
}
// Checks the rows to see wether or not there are 3 of the same values for the rows
bool Board::checkRow() const
{
if(m[0][0] == m[0][1] && m[0][1] == m[0][2] && !fieldEmpty(0,2))
return true;
else if(m[1][0] == m[1][1] && m[1][1] == m[1][2] && !fieldEmpty(1,2))
return true;
else if(m[2][0] == m[2][1] && m[2][1] == m[2][2] && !fieldEmpty(2,2))
return true;
return false;
}
// Checks the rows to see wether or not there are 3 of the same values for the collumns
bool Board::checkCol() const
{
if(m[0][0] == m[1][0] && m[1][0] == m[2][0] && !fieldEmpty(2,0))
return true;
else if(m[0][1] == m[1][1] && m[1][1] == m[2][1] && !fieldEmpty(2,1))
return true;
else if(m[0][2] == m[1][2] && m[1][2] == m[2][2] && !fieldEmpty(2,2))
return true;
return false;
}
// Checks the rows to see wether or not there are 3 of the same values for the diaganols
bool Board::checkDiag() const
{
if(m[0][0] == m[1][1] && m[1][1] == m[2][2] && !fieldEmpty(2,2))
return true;
else if(m[0][2] == m[1][1] && m[1][1] == m[2][0] && !fieldEmpty(2,0))
return true;
return false;
}
void MyApp::mouse_released(int x, int y, uwe::Button button)
{
// Switch case statement to determine variables for buttons
// the user can click to navigate around the game
switch(state)
{
case 0:
bx = 180;
by = 420;
bw = 200;
bh = 100;
break;
case 1:
bx2 = 0;
by2 = 0;
bw2 = 600;
bh2 = 600;
break;
}
if (state == MENU && !b1c)
{
if((x > bx && y > by) && (x < (bx + bw) && y < (by + bh)))
{
board.clearb();
b1c = true;
}
}
if (state == BOARD && !b1c2)
{
if ((x > bx2 && y > by2) && (x < (bx2 + bw2) && y < (by2 + bh2)))
{
b1c2 = true;
}
}
}
void MyApp::draw()
{
if (state == MENU)
{
if (b1c)
{
state = 1;
b1c = false;
clear(uwe::Colour::white());
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
set_draw_color(uwe::Colour::black());
draw_rect((i * width) / 3, (j * height) / 3, width / 3, height / 3);
}
}
}
else
{
//Creates the main menu
clear(uwe::Colour::white());
draw_font(font15_, "Welcome to TicTacToe", 180, 60);
set_draw_color(uwe::Colour::green());
draw_rect_fill(180, 420, 240, 120);
draw_font(font15_, "PLAY!", 260, 460);
}
}
if (state == BOARD)
{
if (playerTurn && b1c2)
{
// Normalises the position of where the user clicked the mouse to the grid
int x, y;
SDL_GetMouseState(&x, &y);
int row = y/(height/3);
int col = x/(width/3);
// Checks to see wether or not the place is free
if (board.fieldEmpty(row, col))
{
// Calls the drawO function to draw the X piece on screen.
drawO(row, col);
// Assigns the correct value to the array for the X Piece
board.m[row][col] = board.PO;
legalMove = true;
b1c2 = false;
// Switches players
playerTurn = !playerTurn;
board.takenPlace++;
// Checks if someone has won yet using pre-defined variables.
if (board.checkCol() == true || board.checkDiag() == true || board.checkRow() == true)
{
state = FINISH;
}
}
}
//
else if(!playerTurn && b1c2)
{
// Normalises the position of where the user clicked the mouse to the grid
int x, y;
SDL_GetMouseState(&x, &y);
int row = y/(height/3);
int col = x/(width/3);
// Checks to see wether or not the place is free
if (board.fieldEmpty(row, col))
{
// Calls the drawX function to draw the X piece on screen.
drawX(row,col);
// Assigns the correct value to the array for the X Piece
board.m[row][col] = board.PX;
legalMove = true;
b1c2 = false;
// Switches players
playerTurn = !playerTurn;
board.takenPlace++;
// Checks if someone has won yet using pre-defined variables.
if (board.checkCol() == true || board.checkDiag() == true || board.checkRow() == true)
{
state = FINISH;
}
}
}
// checks to see if the move was legal and if there has been more than 9 turns taken
else if (legalMove && board.takenPlace >= 9)
{
state = FINISH;
}
// loop to create game board
else
{
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
set_draw_color(uwe::Colour::black());
draw_rect((i * width) / 3, (j * height) / 3, width / 3, height / 3);
}
}
}
}
if (state == FINISH)
{
clear(uwe::Colour::white());
// Switch case statement that works out wether X or O has won based on the number of turns taken.
switch(board.takenPlace){
case 5:
draw_font(font15_, "Congratulations, O won", 180, 60);
break;
case 6:
draw_font(font15_, "Congratulations, X won", 180, 60);
break;
case 7:
draw_font(font15_, "Congratulations, O won", 180, 60);
break;
case 8:
draw_font(font15_, "Congratulations, X won", 180, 60);
break;
case 9:
if (board.checkCol() == true || board.checkDiag() == true || board.checkRow() == true)
{
draw_font(font15_, "Congratulations, O won", 180, 60);
break;
}
else
{
draw_font(font15_, "It was a draw you are both trash", 180, 60);
break;
}
default:
draw_font(font15_, "my spaghetti code broke sorry.", 180, 60);
set_draw_color(uwe::Colour::green());
}
}
}
int main(int argc, char *argv[]) {
uwe::App* app = new MyApp{width, height, "Assignment"};
app->run();
return 0;
}
\ No newline at end of file
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstring>
#include <context.hpp>
#include <app.hpp>
const int width = 640;
const int height = 480;
class MyApp: public uwe::App {
private:
int width_;
int height_;
uwe::Image text_;
int text_width_;
int text_height_;
uwe::Image some_text_;
uwe::Font font15_;
public:
MyApp(int width, int height, std::string title);
~MyApp();
void begin() override;
void update() override;
void draw() override;
void key_pressed(uwe::Scancode scancode, bool repeat) override;
uwe::Image render_text(std::string msg);
};
MyApp::MyApp(int width, int height, std::string title):
width_{width},
height_{height} {
init(width, height, title);
}
MyApp::~MyApp() {
}
void MyApp::begin() {
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
text_ = create_image("./assets/ZX_Spectrum_character_set.png");
#else
text_ = create_image("../assets/ZX_Spectrum_character_set.png");
#endif
get_image_size(text_, &text_width_, &text_height_);
some_text_ = render_text("abc");
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
font15_ = create_font("./assets/fonts/FreeSans.ttf", 15, uwe::Colour::red());
#else
font15_ = create_font("../assets/fonts/FreeSans.ttf", 15, uwe::Colour::red());
#endif
}
void MyApp::update() {
}
void MyApp::key_pressed(uwe::Scancode scancode, bool repeat) {
if( scancode == uwe::Scancode::L) {
toggle_framerate();
}
}
void MyApp::draw() {
clear(uwe::Colour::white());
set_draw_color(uwe::Colour::red());
draw_rect(20,20,100,100);
set_draw_color(uwe::Colour::blue());
draw_rect_fill(100,100,100,100);
draw_line(300, 300, 350, 400);
set_draw_color(uwe::Colour::green());
draw_point(400, 100);
draw_image(text_, uwe::make_rect(0,0,text_width_,text_height_), uwe::make_rect(200,200,text_width_,text_height_));
draw_font(font15_, "This is a msg", 300, 100);
int width;
int height;
get_image_size(some_text_, &width, &height);
draw_image(some_text_, uwe::make_rect(0,0, width, height), uwe::make_rect(150,30, width, height) );
}
uwe::Image MyApp::render_text(std::string msg) {
int max_width = 0;
int num_lines = 1;
int current_width = 0;
for (auto const c : msg) {
if (c != '\n')
current_width++;
else {
num_lines++;
if (current_width > max_width)
max_width = current_width;
current_width = 0;
}
}
if (current_width > max_width) {
max_width = current_width;
}
int text_width = max_width * 16;
int text_height = num_lines * 16;
auto image = create_image(text_width, text_height);
set_draw_color(uwe::Colour::white());
set_renderer_taret(image, true);
int x = 0; int y = 0;
for (auto const c : msg) {
if (c != '\n') {
// Figure out what character it is
int code = c - 32;
if (c == '$') {
code = 64;
}
uwe::Rect src{ (code % 16)*16, (code / 16)*16, 16, 16 };
uwe::Rect dest{ x, y, 16, 16 };
draw_image(text_, src, dest);
x += 16;
} else {
x = 0;
y+=16;
}
}
set_renderer_taret(nullptr, true);
return image;
}
int main(int argc, char *argv[]) {
uwe::App* app = new MyApp{width, height, "Shapes Example"};
app->run();
return 0;
}
\ No newline at end of file
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstring>
#include <context.hpp>
#include <app.hpp>
const int width = 640;
const int height = 480;
class MyApp: public uwe::App {
private:
int width_;
int height_;
public:
MyApp(int width, int height, std::string);
~MyApp();
void begin() override;
void update() override;
void draw() override;
void key_pressed(uwe::Scancode scancode, bool repeat) override;
};
MyApp::MyApp(int width, int height, std::string title):
width_{width},
height_{height} {
init(width, height, title);
}
MyApp::~MyApp() {
}
void MyApp::begin() {
}
void MyApp::update() {
}
void MyApp::key_pressed(uwe::Scancode scancode, bool repeat) {
if( scancode == uwe::Scancode::L) {
toggle_framerate();
}
}
void MyApp::draw() {
clear(uwe::Colour::black());
for( unsigned int i = 0; i < 1000; i++ ) {
const unsigned int x = rand() % get_framebuffer_width();
const unsigned int y = rand() % get_framebuffer_height();
const unsigned int offset = ( get_framebuffer_width() * 4 * y ) + x * 4;
set_framebuffer_non_scaled(
offset,
uwe::Colour{
static_cast<uint8_t>(rand() % 256),
static_cast<uint8_t>(rand() % 256),
static_cast<uint8_t>(rand() % 256),
SDL_ALPHA_OPAQUE});
}
blit_framebuffer();
}
int main( int argc, char** argv ) {
uwe::App* app = new MyApp{width, height, "Splat Example"};
//app->dump_renderer_info();
app->run();
return 0;
}
\ No newline at end of file
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstring>
#include <tuple>
#include <context.hpp>
#include <app.hpp>
using namespace std;
const int width = 640;
const int height = 480;
const int COLOUR_INDEX_X = 30;
const int COLOUR_INDEX_Y = 420;
const int COLOUR_PALATE_WIDTH = 20;
const int COLOUR_PALATE_HEIGHT = 20;
const int COLOUR_CURRENT_X = 30;
const int COLOUR_CURRENT_Y = 30;
const int SPRITE_WIDTH = 16;
const int SPRITE_HEIGHT = 16;
const int SPRITE_DISPLAY_X = 500;
const int SPRITE_DISPLAY_Y = 220;
const int SPRITE_EDITOR_X = 250;
const int SPRITE_EDITOR_Y = 150;
const int SPRITE_EDITOR_PIXELS_WIDTH = 8;
const int SPRITE_EDITOR_PIXELS_HEIGHT = 8;
const int SPRITE_EDITOR_CELL_TIMES = 8;
const int SPRITE_START_X = 100;
const int SPRITE_START_Y = 100;
class MyApp: public uwe::App {
private:
int width_;
int height_;
int colour_index_x_;
int colour_index_y_;
int colour_index_overall_width_;
vector<uwe::Colour> colour_palate_;
uwe::Colour current_colour_;
vector<uwe::Colour> sprite_;
int sprite_x_;
int sprite_y_;
bool mouse_down_;
bool editor_active_;
public:
MyApp(int width, int height, std::string title);
~MyApp();
size_t number_colours() const {
return colour_palate_.size();
}
bool hit_palate(int x, int y, size_t& hit_index) {
if (x >= colour_index_x_ && x <= colour_index_overall_width_ * number_colours() &&
y >= colour_index_y_ && y <= colour_index_y_ + COLOUR_PALATE_HEIGHT) {
hit_index = (x - colour_index_x_) / COLOUR_PALATE_WIDTH;
return true;
}
return false;
}
bool hit_editor(int x, int y, size_t& hit_index) {
if (x >= SPRITE_EDITOR_X && x <= SPRITE_EDITOR_X + SPRITE_EDITOR_PIXELS_WIDTH*SPRITE_WIDTH &&
y >= SPRITE_EDITOR_Y && y <= SPRITE_EDITOR_Y + SPRITE_EDITOR_PIXELS_HEIGHT*SPRITE_HEIGHT ) {
hit_index = (x - SPRITE_EDITOR_X) / (SPRITE_EDITOR_PIXELS_WIDTH);
int tmp = (y - SPRITE_EDITOR_Y) / SPRITE_EDITOR_PIXELS_HEIGHT;
hit_index = hit_index + SPRITE_WIDTH*tmp;
return true;
}
return false;
}
void begin() override;
void update() override;
void draw() override;
void key_pressed(uwe::Scancode scancode, bool repeat) override;
void mouse_pressed(int x, int y, uwe::Button button) override;
void mouse_released(int x, int y, uwe::Button button) override;
void mouse_moved(int x, int y) override;
};
MyApp::MyApp(int width, int height, std::string title):
width_{width},
height_{height},
colour_index_x_{COLOUR_INDEX_X},
colour_index_y_{COLOUR_INDEX_Y},
current_colour_{uwe::Colour::black()},
sprite_(SPRITE_WIDTH*SPRITE_HEIGHT, uwe::Colour::white()),
mouse_down_{false},
editor_active_{false},
sprite_x_{SPRITE_START_X},
sprite_y_{SPRITE_START_Y} {
init(width, height, title);
colour_palate_.push_back(uwe::Colour::white());
colour_palate_.push_back(uwe::Colour::green());
colour_palate_.push_back(uwe::Colour::blue());
colour_palate_.push_back(uwe::Colour::red());
colour_index_overall_width_ = COLOUR_PALATE_WIDTH * number_colours();
current_colour_ = colour_palate_[0];
}
MyApp::~MyApp() {
}
void MyApp::begin() {
}
void MyApp::update() {
}
void MyApp::key_pressed(uwe::Scancode scancode, bool repeat) {
switch (scancode) {
// enable framerate dump
case uwe::Scancode::L: {
toggle_framerate();
break;
}
// switch to editor
case uwe::Scancode::D_1: {
editor_active_ = false;
break;
}
// switch to scene
case uwe::Scancode::D_2: {
editor_active_ = true;
break;
}
case uwe::Scancode::LEFT: {
if (!editor_active_) {
sprite_x_ = sprite_x_ - 2;
}
break;
// TODO: bounds check against window
}
case uwe::Scancode::RIGHT: {
if (!editor_active_) {
sprite_x_ = sprite_x_ + 2;
}
break;
}
case uwe::Scancode::UP: {
if (!editor_active_) {
sprite_y_ = sprite_y_ - 4;
}
break;
}
case uwe::Scancode::DOWN: {
if (!editor_active_) {
sprite_y_ = sprite_y_ + 2;
}
break;
}
default: {
// nothing see here
}
}
}
void MyApp::mouse_pressed(int x, int y, uwe::Button button) {
if (editor_active_) {
size_t hit_index;
if (hit_palate(x, y, hit_index)) {
current_colour_ = colour_palate_[hit_index];
}
else if (hit_editor(x, y, hit_index)) {
sprite_[hit_index] = current_colour_;
}
}
mouse_down_ = true;
}
void MyApp::mouse_released(int x, int y, uwe::Button button) {
mouse_down_ = false;
}
void MyApp::mouse_moved(int x, int y) {
size_t hit_index;
if (mouse_down_ && hit_editor(x, y, hit_index)) {
sprite_[hit_index] = current_colour_;
}
}
void MyApp::draw() {
clear(uwe::Colour::black());
// Below we demostrate the use of both the framebuffer and drawing primitives.
clear_framebuffer(uwe::Colour::black());
if (editor_active_) {
// draw sprite as actually seen
int i = 0;
for (int y = 0; y < SPRITE_HEIGHT; y++) {
for (int x = 0; x < SPRITE_WIDTH; x++) {
// draw sprite as actually seen
set_framebuffer(x + SPRITE_DISPLAY_X, y + SPRITE_DISPLAY_Y, sprite_[i]);
// draw sprite editor
for (int y_times = 0; y_times < SPRITE_EDITOR_PIXELS_HEIGHT; y_times++) {
for (int x_times = 0; x_times < SPRITE_EDITOR_PIXELS_WIDTH; x_times++) {
set_framebuffer(
x*SPRITE_EDITOR_PIXELS_WIDTH + SPRITE_EDITOR_X + x_times,
y*SPRITE_EDITOR_PIXELS_HEIGHT + SPRITE_EDITOR_Y + y_times,
sprite_[i]);
}
}
i++;
}
}
blit_framebuffer();
// draw colour palate
for (int i = 0; i < number_colours(); i++) {
set_draw_color(colour_palate_[i]);
draw_rect_fill(
colour_index_x_ + i*COLOUR_PALATE_WIDTH, colour_index_y_, COLOUR_PALATE_WIDTH, COLOUR_PALATE_HEIGHT);
}
// draw current colour
set_draw_color(current_colour_);
draw_rect_fill(COLOUR_CURRENT_X, COLOUR_CURRENT_Y, COLOUR_PALATE_WIDTH, COLOUR_PALATE_HEIGHT);
}
else {
// draw scene
int i = 0;
for (int y = 0; y < SPRITE_HEIGHT; y++) {
for (int x = 0; x < SPRITE_WIDTH; x++) {
// draw sprite as actually seen
set_framebuffer(x + sprite_x_, y + sprite_y_, sprite_[i]);
i++;
}
}
blit_framebuffer();
}
}
int main(int argc, char *argv[]) {
uwe::App* app = new MyApp{width, height, "Sprite Example"};
app->run();
return 0;
}
\ No newline at end of file
/*
SDL_FontCache v0.10.0: A font cache for SDL and SDL_ttf
by Jonathan Dearborn
Dedicated to the memory of Florian Hufsky
License:
The short:
Use it however you'd like, but keep the copyright and license notice
whenever these files or parts of them are distributed in uncompiled form.
The long:
Copyright (c) 2019 Jonathan Dearborn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _SDL_FONTCACHE_H__
#define _SDL_FONTCACHE_H__
#include "SDL.h"
#include "SDL_ttf.h"
#ifdef FC_USE_SDL_GPU
#include "SDL_gpu.h"
#endif
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
// Let's pretend this exists...
#define TTF_STYLE_OUTLINE 16
// Differences between SDL_Renderer and SDL_gpu
#ifdef FC_USE_SDL_GPU
#define FC_Rect GPU_Rect
#define FC_Target GPU_Target
#define FC_Image GPU_Image
#define FC_Log GPU_LogError
#else
#define FC_Rect SDL_Rect
#define FC_Target SDL_Renderer
#define FC_Image SDL_Texture
#define FC_Log SDL_Log
#endif
// SDL_FontCache types
typedef enum
{
FC_ALIGN_LEFT,
FC_ALIGN_CENTER,
FC_ALIGN_RIGHT
} FC_AlignEnum;
typedef enum
{
FC_FILTER_NEAREST,
FC_FILTER_LINEAR
} FC_FilterEnum;
typedef struct FC_Scale
{
float x;
float y;
} FC_Scale;
typedef struct FC_Effect
{
FC_AlignEnum alignment;
FC_Scale scale;
SDL_Color color;
} FC_Effect;
// Opaque type
typedef struct FC_Font FC_Font;
typedef struct FC_GlyphData
{
SDL_Rect rect;
int cache_level;
} FC_GlyphData;
// Object creation
FC_Rect FC_MakeRect(float x, float y, float w, float h);
FC_Scale FC_MakeScale(float x, float y);
SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color);
FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h);
// Font object
FC_Font* FC_CreateFont(void);
#ifdef FC_USE_SDL_GPU
Uint8 FC_LoadFont(FC_Font* font, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style);
Uint8 FC_LoadFontFromTTF(FC_Font* font, TTF_Font* ttf, SDL_Color color);
Uint8 FC_LoadFont_RW(FC_Font* font, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style);
#else
Uint8 FC_LoadFont(FC_Font* font, SDL_Renderer* renderer, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style);
Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, SDL_Color color);
Uint8 FC_LoadFont_RW(FC_Font* font, SDL_Renderer* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style);
#endif
#ifndef FC_USE_SDL_GPU
// note: handle SDL event types SDL_RENDER_TARGETS_RESET(>= SDL 2.0.2) and SDL_RENDER_DEVICE_RESET(>= SDL 2.0.4)
void FC_ResetFontFromRendererReset(FC_Font* font, SDL_Renderer* renderer, Uint32 evType);
#endif
void FC_ClearFont(FC_Font* font);
void FC_FreeFont(FC_Font* font);
// Built-in loading strings
char* FC_GetStringASCII(void);
char* FC_GetStringLatin1(void);
char* FC_GetStringASCII_Latin1(void);
// UTF-8 to SDL_FontCache codepoint conversion
/*!
Returns the Uint32 codepoint (not UTF-32) parsed from the given UTF-8 string.
\param c A pointer to a string of proper UTF-8 character values.
\param advance_pointer If true, the source pointer will be incremented to skip the extra bytes from multibyte codepoints.
*/
Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer);
/*!
Parses the given codepoint and stores the UTF-8 bytes in 'result'. The result is NULL terminated.
\param result A memory buffer for the UTF-8 values. Must be at least 5 bytes long.
\param codepoint The Uint32 codepoint to parse (not UTF-32).
*/
void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint);
// UTF-8 string operations
/*! Allocates a new string of 'size' bytes that is already NULL-terminated. The NULL byte counts toward the size limit, as usual. Returns NULL if size is 0. */
char* U8_alloc(unsigned int size);
/*! Deallocates the given string. */
void U8_free(char* string);
/*! Allocates a copy of the given string. */
char* U8_strdup(const char* string);
/*! Returns the number of UTF-8 characters in the given string. */
int U8_strlen(const char* string);
/*! Returns the number of bytes in the UTF-8 multibyte character pointed at by 'character'. */
int U8_charsize(const char* character);
/*! Copies the source multibyte character into the given buffer without overrunning it. Returns 0 on failure. */
int U8_charcpy(char* buffer, const char* source, int buffer_size);
/*! Returns a pointer to the next UTF-8 character. */
const char* U8_next(const char* string);
/*! Inserts a UTF-8 string into 'string' at the given position. Use a position of -1 to append. Returns 0 when unable to insert the string. */
int U8_strinsert(char* string, int position, const char* source, int max_bytes);
/*! Erases the UTF-8 character at the given position, moving the subsequent characters down. */
void U8_strdel(char* string, int position);
// Internal settings
/*! Sets the string from which to load the initial glyphs. Use this if you need upfront loading for any reason (such as lack of render-target support). */
void FC_SetLoadingString(FC_Font* font, const char* string);
/*! Returns the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */
unsigned int FC_GetBufferSize(void);
/*! Changes the size of the internal buffer which is used for unpacking variadic text data. This buffer is shared by all FC_Fonts. */
void FC_SetBufferSize(unsigned int size);
/*! Returns the width of a single horizontal tab in multiples of the width of a space (default: 4) */
unsigned int FC_GetTabWidth(void);
/*! Changes the width of a horizontal tab in multiples of the width of a space (default: 4) */
void FC_SetTabWidth(unsigned int width_in_spaces);
void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale));
FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale);
// Custom caching
/*! Returns the number of cache levels that are active. */
int FC_GetNumCacheLevels(FC_Font* font);
/*! Returns the cache source texture at the given cache level. */
FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level);
// TODO: Specify ownership of the texture (should be shareable)
/*! Sets a cache source texture for rendering. New cache levels must be sequential. */
Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture);
/*! Copies the given surface to the given cache level as a texture. New cache levels must be sequential. */
Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface);
/*! Returns the number of codepoints that are stored in the font's glyph data map. */
unsigned int FC_GetNumCodepoints(FC_Font* font);
/*! Copies the stored codepoints into the given array. */
void FC_GetCodepoints(FC_Font* font, Uint32* result);
/*! Stores the glyph data for the given codepoint in 'result'. Returns 0 if the codepoint was not found in the cache. */
Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint);
/*! Sets the glyph data for the given codepoint. Duplicates are not checked. Returns a pointer to the stored data. */
FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data);
// Rendering
FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...);
FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...);
FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...);
FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...);
FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...);
FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...);
FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...);
FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...);
FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...);
FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...);
FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...);
FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...);
FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...);
FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...);
FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...);
// Getters
FC_FilterEnum FC_GetFilterMode(FC_Font* font);
Uint16 FC_GetLineHeight(FC_Font* font);
Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...);
Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...);
// Returns a 1-pixel wide box in front of the character in the given position (index)
FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...);
Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...);
int FC_GetAscent(FC_Font* font, const char* formatted_text, ...);
int FC_GetDescent(FC_Font* font, const char* formatted_text, ...);
int FC_GetBaseline(FC_Font* font);
int FC_GetSpacing(FC_Font* font);
int FC_GetLineSpacing(FC_Font* font);
Uint16 FC_GetMaxWidth(FC_Font* font);
SDL_Color FC_GetDefaultColor(FC_Font* font);
FC_Rect FC_GetBounds(FC_Font* font, float x, float y, FC_AlignEnum align, FC_Scale scale, const char* formatted_text, ...);
Uint8 FC_InRect(float x, float y, FC_Rect input_rect);
// Given an offset (x,y) from the text draw position (the upper-left corner), returns the character position (UTF-8 index)
Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...);
// Returns the number of characters in the new wrapped text written into `result`.
int FC_GetWrappedText(FC_Font* font, char* result, int max_result_size, Uint16 width, const char* formatted_text, ...);
// Setters
void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter);
void FC_SetSpacing(FC_Font* font, int LetterSpacing);
void FC_SetLineSpacing(FC_Font* font, int LineSpacing);
void FC_SetDefaultColor(FC_Font* font, SDL_Color color);
#ifdef __cplusplus
}
#endif
#endif