From 9ae3eb011f0c93fb0fcdb672f82ead2b1e48b2f9 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 27 Nov 2024 16:10:31 +0100 Subject: [PATCH] feat: raycasting functionnal --- Cub3D 2 | Bin 0 -> 81960 bytes Makefile | 10 +- Makefile.gen | 1 + includes/cub3d.h | 3 +- includes/cub3d_struct.h | 4 +- libft/compilation.log | 4 - mlx_layer/mlx_init.c | 27 +++-- raycast/rc_utils.c | 139 ++++++++++----------- test/.envrc | 1 + test/Makefile | 146 ++++++++++++++++++++++ test/Makefile.gen | 1 + test/flake.lock | 143 ++++++++++++++++++++++ test/flake.nix | 31 +++++ test/minilibx-linux | 1 + test/test.c | 263 ++++++++++++++++++++++++++++++++++++++++ test/test.h | 45 +++++++ test/test2.c | 262 +++++++++++++++++++++++++++++++++++++++ test/textures/a.xpm | 154 +++++++++++++++++++++++ test/textures/b.xpm | 49 ++++++++ 19 files changed, 1183 insertions(+), 101 deletions(-) create mode 100755 Cub3D 2 create mode 100644 Makefile.gen delete mode 100644 libft/compilation.log create mode 100644 test/.envrc create mode 100644 test/Makefile create mode 100644 test/Makefile.gen create mode 100644 test/flake.lock create mode 100644 test/flake.nix create mode 160000 test/minilibx-linux create mode 100644 test/test.c create mode 100644 test/test.h create mode 100644 test/test2.c create mode 100644 test/textures/a.xpm create mode 100644 test/textures/b.xpm diff --git a/Cub3D 2 b/Cub3D 2 new file mode 100755 index 0000000000000000000000000000000000000000..b4309a9ac80ee36569fde7a41f13b4259f84df05 GIT binary patch literal 81960 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 +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2023/11/12 11:05:05 by rparodi #+# #+# # -# Updated: 2024/11/23 12:41:29 by rparodi ### ########.fr # +# Updated: 2024/11/27 16:05:42 by rparodi ### ########.fr # # # # **************************************************************************** # @@ -26,8 +26,8 @@ CFLAGS += -g3 -MMD # CFLAGS += -fsanitize=address # CFLAGS += -fsanitize=thread -# INCLUDES += -I /opt/X11/include -INCLUDES = -I /usr/include -I ./includes -I ./includes/include -I ./minilibx-linux +INCLUDES += -I /opt/X11/include +INCLUDES = -I ./includes -I ./includes/include -I ./minilibx-linux # Paths LIBFT_DIR = ./libft @@ -37,8 +37,8 @@ MLX_DIR = ./minilibx-linux LDFLAGS = -L./build -lft -lm # MiniLibX flags for macOS with XQuartz -MLXFLAGS = -L$(MLX_DIR) -lmlx -lX11 -lXext -lXrender -lXrandr -lXi -#MLXFLAGS += -L/opt/X11/lib +MLXFLAGS = -L$(MLX_DIR) -lmlx -lX11 -lXext +MLXFLAGS += -L/opt/X11/lib # Add MLXFLAGS to the linker flags LDFLAGS += $(MLXFLAGS) diff --git a/Makefile.gen b/Makefile.gen new file mode 100644 index 0000000..60181d4 --- /dev/null +++ b/Makefile.gen @@ -0,0 +1 @@ +INC=/usr/X11/include diff --git a/includes/cub3d.h b/includes/cub3d.h index b07c25c..43386a5 100644 --- a/includes/cub3d.h +++ b/includes/cub3d.h @@ -6,7 +6,7 @@ /* By: rparodi +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/10/30 16:30:26 by rparodi #+# #+# */ -/* Updated: 2024/11/20 13:55:10 by rparodi ### ########.fr */ +/* Updated: 2024/11/26 13:37:20 by rparodi ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,5 +38,6 @@ void parse_map(t_info *info); void parse_args(char *arg, t_info *inf); int main(int argc, char *argv[]); +void shelves_launch(t_info *info); #endif /* CUB3D_H */ diff --git a/includes/cub3d_struct.h b/includes/cub3d_struct.h index 8516dd2..211541f 100644 --- a/includes/cub3d_struct.h +++ b/includes/cub3d_struct.h @@ -6,7 +6,7 @@ /* By: bgoulard +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/11/08 23:55:29 by bgoulard #+# #+# */ -/* Updated: 2024/11/20 15:13:28 by rparodi ### ########.fr */ +/* Updated: 2024/11/26 13:35:13 by rparodi ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,8 @@ # define FILE_EXTENSION ".cub" # define FILE_EXTENSION_LEN 4 +#define FOV 65 +#define TILE_SIZE 64 // -- graphic utils typedef struct s_color diff --git a/libft/compilation.log b/libft/compilation.log deleted file mode 100644 index 707331c..0000000 --- a/libft/compilation.log +++ /dev/null @@ -1,4 +0,0 @@ -src/ft_string/ft_chr/ft_putchar_fd.c:17:2: error: ignoring return value of function declared with 'warn_unused_result' attribute [-Werror,-Wunused-result] - 17 | write(fd, &c, 1); - |  ^~~~~ ~~~~~~~~~ -1 error generated. diff --git a/mlx_layer/mlx_init.c b/mlx_layer/mlx_init.c index df0abcc..db5c801 100644 --- a/mlx_layer/mlx_init.c +++ b/mlx_layer/mlx_init.c @@ -6,7 +6,7 @@ /* By: rparodi +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/11/11 19:53:42 by rparodi #+# #+# */ -/* Updated: 2024/11/22 15:17:07 by rparodi ### ########.fr */ +/* Updated: 2024/11/26 13:40:17 by rparodi ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,17 +32,17 @@ int c3_redcross(t_info *info) { return (mlx_loop_end(info->mlx_ptr), EXIT_SUCCESS); } -t_win_list *c3_init_mlx_window(t_info *info); -/*t_win_list *c3_init_mlx_window(t_info *info)*/ -/*{*/ -/* int x;*/ -/* int y;*/ -/**/ -/* x = 0;*/ -/* y = 0;*/ -/* mlx_get_screen_size(info->mlx_ptr, &x, &y);*/ -/* return (mlx_new_window(info->mlx_ptr, x, y, "C3D"));*/ -/*}*/ + +t_win_list *c3_init_mlx_window(t_info *info) +{ + int x; + int y; + + x = 0; + y = 0; + mlx_get_screen_size(info->mlx_ptr, &x, &y); + return (mlx_new_window(info->mlx_ptr, x, y, "C3D")); +} int init_mlx_env(t_info *info) { @@ -54,6 +54,7 @@ int init_mlx_env(t_info *info) return (ERROR_MLX); mlx_hook(info->win_ptr, KeyPress, KeyPressMask, c3_keyhook, info); mlx_hook(info->win_ptr, DestroyNotify, StructureNotifyMask, c3_redcross, info); - mlx_loop_hook(info->mlx_ptr, c3_frame_update, info); + mlx_loop_hook(info->mlx_ptr, (int (*)())shelves_launch, &info); + /*mlx_loop_hook(info->mlx_ptr, c3_frame_update, info);*/ return (NO_ERROR); } diff --git a/raycast/rc_utils.c b/raycast/rc_utils.c index c6bca11..971edf6 100644 --- a/raycast/rc_utils.c +++ b/raycast/rc_utils.c @@ -6,7 +6,7 @@ /* By: rparodi +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/11/12 12:24:35 by rparodi #+# #+# */ -/* Updated: 2024/11/23 12:33:39 by rparodi ### ########.fr */ +/* Updated: 2024/11/26 13:39:56 by rparodi ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,91 +27,76 @@ double cub_convert_deg_to_rad(double degrees) } /** - * @brief Launches a ray for raycasting to determine the distance to the first wall. + * @brief Launches a ray for raycasting to determine the distance to the first wall. * * This function calculates the distance of a ray cast in a specified angle * until it either hits a wall or reaches the maximum range. * - * @param info A pointer to the `t_info` structure containing the map and other relevant data. + + * @param info A pointer to the `t_info` structure containing the map and other relevant data. * @param angle The angle of the ray being cast, in radians. * * @return The distance from the starting position to the first wall hit. - * If no wall is hit within `MAX_RANGE`, the function returns `MAX_RANGE`. + * If no wall is hit within `MAX_RANGE`, + the function returns `MAX_RANGE`. */ - double rc_launch(t_info *info, double angle) - { - double distance; - t_dpoint direction; - t_dpoint rayon; - - distance = 0; - direction.x = cos(angle); - direction.y = sin(angle); - rayon.x = 0; - rayon.y = 0; - while (distance < MAX_RANGE) - { - rayon.x = direction.x * distance; - rayon.y = direction.y * distance; - if (info->map.map[(int)info->map.fraw[(int)rayon.x][(int)rayon.y]] == '1') - return (distance); - distance += STEP_SIZE; - } - return (MAX_RANGE); - } - - /** - * @brief Launches algorithm over a specified width with angle adjustments. - * - * @param info The structure of the game (for the view) - * @param spacing The spacing between rays. - * @param focal The focal length affecting the angle adjustment. - * @param width The total width (number of columns) to iterate over. - * - * @note The function assumes `rc_launch` is defined elsewhere to handle the angle. - */ - void shelves_launch(t_info *info, double spacing, double focal, int width) - { - int x; - double angle; - - x = 0; - while (x < width) - { - angle = info->player.view + atan(\ - (spacing / 2 - x * spacing / (width - 1)) / focal); - rc_launch(info, angle); - x++; - } - } - -t_win_list *c3_init_mlx_window(t_info *info) +double rc_launch(t_info *info, double angle) { - void *window; - int i; - int j; - int x; - int y; + double distance = 0; + t_dpoint direction = { cos(angle), sin(angle) }; + t_dpoint rayon = { 0, 0 }; - x = 0; - y = 0; - mlx_get_screen_size(info->mlx_ptr, &x, &y); - - i = 0; - window = mlx_new_window(info->mlx_ptr, x, y, "Raycasting"); - while (i < x) + while (distance < MAX_RANGE) { - j = 0; - while (j < y) - { - if (info->map.fraw[i / info->map.size.x][j / info->map.size.y] == '1') - mlx_pixel_put(info->mlx_ptr, window, i, j, 0xFFFFFF); - else - mlx_pixel_put(info->mlx_ptr, window, i, j, 0x000000); - j++; - } - i++; + rayon.x = info->player.pos.x + direction.x * distance; + rayon.y = info->player.pos.y + direction.y * distance; + if (info->map.fraw[(int)(rayon.y)][(int)(rayon.x)] == '1') + return (distance); + distance += STEP_SIZE; } - mlx_loop(info->mlx_ptr); - return (window); - } + return (MAX_RANGE); +} + +/** + * @brief Launches algorithm over a specified width with angle adjustments. + * + * @param info The structure of the game (for the view) + * @param spacing The spacing between rays. + * @param focal The focal length affecting the angle adjustment. + * @param width The total width (number of columns) to iterate over. + * + + * @note The function assumes `rc_launch` is defined elsewhere to handle the angle. + */ + +void draw_line(t_info *info, int x, int start, int end, unsigned int color) +{ + while (start <= end) + { + mlx_pixel_put(info->mlx_ptr, info->win_ptr, x, start, color); + start++; + } +} + +void shelves_launch(t_info *info) +{ + info->player.pos = (t_dpoint){ 4.5, 4.5 }; // Starting in the middle of the map + info->player.view = 0; int x; + double angle; + double distance; + double projection_plane = info->map.size.x / (2.0 * tan(M_PI / 6.0)); + + for (x = 0; x < info->map.size.x; x++) + { + angle = info->player.view + atan((x - info->map.size.x / 2.0) / projection_plane); + distance = rc_launch(info, angle); + int line_height = (int)(TILE_SIZE / distance * projection_plane); + int start = (info->map.size.y / 2) - (line_height / 2); + int end = (info->map.size.y / 2) + (line_height / 2); + + if (start < 0) start = 0; + if (end >= info->map.size.y) end = info->map.size.y - 1; + + draw_line(info, x, start, end, 0xFFFFFF); + } +} diff --git a/test/.envrc b/test/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/test/.envrc @@ -0,0 +1 @@ +use flake diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..854d6d2 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,146 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: rparodi +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2023/11/12 11:05:05 by rparodi #+# #+# # +# Updated: 2024/11/26 14:41:12 by rparodi ### ########.fr # +# # +# **************************************************************************** # + +# Variables + +# Name +NAME = Cub3D +NAME_BONUS = Cub3D_bonus + +# Commands +CC = cc +RM = rm -rf + +# Flags +CFLAGS = -Werror -Wextra -Wall +CFLAGS += -g3 -MMD +# CFLAGS += -fsanitize=address +# CFLAGS += -fsanitize=thread + +# INCLUDES += -I /opt/X11/include +INCLUDES = -I /usr/include -I ./includes -I ./includes/include -I ./minilibx-linux + +# Paths +MLX_DIR = ./minilibx-linux + +# Library flags +LDFLAGS = -L./build -lm + +# MiniLibX flags for macOS with XQuartz +MLXFLAGS = -L$(MLX_DIR) -lmlx -lX11 -lXext +#MLXFLAGS += -L/opt/X11/lib + +# Add MLXFLAGS to the linker flags +LDFLAGS += $(MLXFLAGS) + +SRC = test2.c + +# Objects +OBJDIRNAME = ./build +OBJ = $(addprefix $(OBJDIRNAME)/,$(SRC:.c=.o)) + +# Colors +GREEN = \033[32m +GREY = \033[0;90m +RED = \033[0;31m +GOLD = \033[38;5;220m +END = \033[0m + +# Rules +# +# All (make all) +all: header $(NAME) footer + +# Bonus (make bonus) +bonus: header $(OBJ) footer + @mkdir -p $(OBJDIRNAME) + @printf '$(GREY) Creating $(END)$(GREEN)$(OBJDIRNAME)$(END)\n' + @$(CC) $(CFLAGS) -D BONUS=1 -o $(NAME_BONUS) $(OBJ) $(LDFLAGS) + +# Clean (make clean) +clean: + @printf '$(GREY) Removing $(END)$(RED)Objects$(END)\n' + @printf '$(GREY) Removing $(END)$(RED)Objects Folder$(END)\n' + @$(RM) $(OBJDIRNAME) + +# Clean (make fclean) +fclean: clean + @printf '$(GREY) Removing $(END)$(RED)Program$(END)\n' + @$(RM) $(NAME) + @$(RM) $(NAME_BONUS) + @echo "" + +# Restart (make re) +re: header fclean all + +# Compile external libraries +build/libmlx.a: + @make --no-print-directory -C $(MLX_DIR) + +# Dependences for all +$(NAME): $(OBJ) build/libmlx.a + @mkdir -p $(OBJDIRNAME) + @printf '$(GREY) Creating $(END)$(GREEN)$(OBJDIRNAME)$(END)\n' + @$(CC) $(CFLAGS) $(OBJ) $(LDFLAGS) -o $(NAME) + +# Creating the objects +$(OBJDIRNAME)/%.o: %.c + @mkdir -p $(dir $@) + @printf '$(GREY) Compiling $(END)$(GREEN)$<$(END)\n' + @$(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $< + +# Header +header: + @clear + @printf '\n\n' + @printf '$(GOLD) ******* ****** ******* $(END)\n' + @printf '$(GOLD) ****** *** ******* $(END)\n' + @printf '$(GOLD) ******* * ******* $(END)\n' + @printf '$(GOLD) ****** ******* $(END)\n' + @printf '$(GOLD) ******* ******* $(END)\n' + @printf '$(GOLD) ******************* ******* * $(END)\n' + @printf '$(GOLD) ******************* ******* *** $(END)\n' + @printf '$(GOLD) ****** ******* ****** $(END)\n' + @printf '$(GOLD) ****** $(END)\n' + @printf '$(GOLD) ****** $(END)\n' + @printf '$(GREY) Made by rparodi$(END)\n\n' + +# Footer +footer: + @printf "\n" + @printf "$(GOLD) ,_ _,$(END)\n" + @printf "$(GOLD) | \\___//|$(END)\n" + @printf "$(GOLD) |=6 6=|$(END)\n" + @printf "$(GOLD) \\=._Y_.=/$(END)\n" + @printf "$(GOLD) ) \` ( ,$(END)\n" + @printf "$(GOLD) / \\ (('$(END)\n" + @printf "$(GOLD) | | ))$(END)\n" + @printf "$(GOLD) /| | | |\\_//$(END)\n" + @printf "$(GOLD) \\| |._.| |/-\`$(END)\n" + @printf "$(GOLD) '\"' '\"'$(END)\n" + @printf ' $(GREY)The compilation is$(END) $(GOLD)finish$(END)\n $(GREY)Have a good $(END)$(GOLD)correction !$(END)\n' + +clangd: + @echo -en \ + "CompileFlags:\n" \ + " Add:\n" \ + " - \"-Wall -Wextra -Werror\"\n" \ + " - \"-I/opt/X11/include\"\n" \ + " - \"-I"$(shell pwd)"/includes\"\n" \ + " - \"-I"$(shell pwd)"/includes/include\"\n" \ + " - \"-xc\"\n" \ + > .clangd + +# Phony targets +.PHONY: all bonus clean fclean re + +-include ${OBJ:.o=.d} diff --git a/test/Makefile.gen b/test/Makefile.gen new file mode 100644 index 0000000..60181d4 --- /dev/null +++ b/test/Makefile.gen @@ -0,0 +1 @@ +INC=/usr/X11/include diff --git a/test/flake.lock b/test/flake.lock new file mode 100644 index 0000000..6db3dfb --- /dev/null +++ b/test/flake.lock @@ -0,0 +1,143 @@ +{ + "nodes": { + "c_formatter_42": { + "inputs": { + "c_formatter_42_src": "c_formatter_42_src", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1731759938, + "narHash": "sha256-3cVAExF4GFXXMd72AUUNgBn3p6W/8HIpYpeXvczK3Bo=", + "owner": "maix0", + "repo": "c_formatter_42-flake", + "rev": "26b2a2b774669d10bc50ab624ef58ed48ca2e9ec", + "type": "github" + }, + "original": { + "owner": "maix0", + "repo": "c_formatter_42-flake", + "type": "github" + } + }, + "c_formatter_42_src": { + "flake": false, + "locked": { + "lastModified": 1727700580, + "narHash": "sha256-GFnYVipVE6G1GFUqAzRkBSg7GgPgcLWX48GZtmM4i2Q=", + "owner": "dawnbeen", + "repo": "c_formatter_42", + "rev": "a255930b4be508a94bf6d8523d96556bdb4660ad", + "type": "github" + }, + "original": { + "owner": "dawnbeen", + "repo": "c_formatter_42", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 0, + "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "path": "/nix/store/zq2axpgzd5kykk1v446rkffj3bxa2m2h-source", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1732014248, + "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "c_formatter_42": "c_formatter_42", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/test/flake.nix b/test/flake.nix new file mode 100644 index 0000000..b62b26c --- /dev/null +++ b/test/flake.nix @@ -0,0 +1,31 @@ +{ + description = "Flake utils demo"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + c_formatter_42.url = "github:maix0/c_formatter_42-flake"; + }; + outputs = { + self, + nixpkgs, + flake-utils, + c_formatter_42, + }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShell = pkgs.mkShell { + packages = [ + pkgs.xorg.libX11 + pkgs.xorg.libXext + pkgs.clang + pkgs.clang-tools + pkgs.norminette + c_formatter_42.packages.${system}.default + ]; + }; + } + ); +} diff --git a/test/minilibx-linux b/test/minilibx-linux new file mode 160000 index 0000000..7dc53a4 --- /dev/null +++ b/test/minilibx-linux @@ -0,0 +1 @@ +Subproject commit 7dc53a411a7d4ae286c60c6229bd1e395b0efb82 diff --git a/test/test.c b/test/test.c new file mode 100644 index 0000000..f5fa61b --- /dev/null +++ b/test/test.c @@ -0,0 +1,263 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/27 12:09:00 by rparodi #+# #+# */ +/* Updated: 2024/11/27 15:59:53 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "test.h" + +int worldMap[MAP_WIDTH][MAP_HEIGHT] = {\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} \ +}; + +void my_mlx_pixel_put(t_data *data, int x, int y, int color) +{ + char *dst; + + dst = data->addr + (y * data->line_length + x * (data->bits_per_pixel / 8)); + *(unsigned int *)dst = color; +} + +void move_straight(t_data *data) +{ + if (!worldMap[\ + (int)(data->pos_x + data->dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x += data->dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y + data->dir_y * MOVE_SPEED)]) + data->pos_y += data->dir_y * MOVE_SPEED; +} + +void move_backward(t_data *data) +{ + if (!worldMap[\ + (int)(data->pos_x - data->dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x -= data->dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y - data->dir_y * MOVE_SPEED)]) + data->pos_y -= data->dir_y * MOVE_SPEED; +} + +void move_left(t_data *data) +{ + double perp_dir_x; + double perp_dir_y; + + perp_dir_x = -data->dir_y; + perp_dir_y = data->dir_x; + if (!worldMap[\ + (int)(data->pos_x + perp_dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x -= perp_dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y - perp_dir_y * MOVE_SPEED)]) + data->pos_y -= perp_dir_y * MOVE_SPEED; +} + +void move_right(t_data *data) +{ + double perp_dir_x; + double perp_dir_y; + + perp_dir_x = -data->dir_y; + perp_dir_y = data->dir_x; + if (!worldMap[\ + (int)(data->pos_x - perp_dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x += perp_dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y + perp_dir_y * MOVE_SPEED)]) + data->pos_y += perp_dir_y * MOVE_SPEED; +} + +void look_left(t_data *data) +{ + double old_dir_x; + double old_plane_x; + + old_dir_x = data->dir_x; + old_plane_x = data->plane_x; + data->dir_x = data->dir_x * cos(ROT_SPEED) - data->dir_y * sin(ROT_SPEED); + data->dir_y = old_dir_x * sin(ROT_SPEED) + data->dir_y * cos(ROT_SPEED); + data->plane_x = data->plane_x * cos(ROT_SPEED) \ + - data->plane_y * sin(ROT_SPEED); + data->plane_y = old_plane_x * sin(ROT_SPEED) \ + + data->plane_y * cos(ROT_SPEED); +} + +void look_right(t_data *data) +{ + double old_dir_x; + double old_plane_x; + + old_dir_x = data->dir_x; + old_plane_x = data->plane_x; + data->dir_x = data->dir_x * cos(-ROT_SPEED) - data->dir_y * sin(-ROT_SPEED); + data->dir_y = old_dir_x * sin(-ROT_SPEED) + data->dir_y * cos(-ROT_SPEED); + data->plane_x = data->plane_x * cos(-ROT_SPEED) \ + - data->plane_y * sin(-ROT_SPEED); + data->plane_y = old_plane_x * sin(-ROT_SPEED) \ + + data->plane_y * cos(-ROT_SPEED); +} + +int key_hook(int keycode, t_data *data) +{ + if (keycode == 65307) + exit(0); + if (keycode == 119) + move_straight(data); + if (keycode == 115) + move_backward(data); + if (keycode == 97) + move_right(data); + if (keycode == 100) + move_left(data); + if (keycode == 65361) + look_left(data); + if (keycode == 65363) + look_right(data); + return (0); +} + +int render_frame(t_data *data) +{ + int y; + int x; + + y = 0; + while (y < WINDOW_HEIGHT) + { + x = 0; + while (x < WINDOW_WIDTH) + { + my_mlx_pixel_put(data, x, y, 0x00000000); + x++; + } + y++; + } + + for(int x = 0; x < WINDOW_WIDTH; x++) + { + double cameraX = 2 * x / (double)WINDOW_WIDTH - 1; + double rayDirX = data->dir_x + data->plane_x * cameraX; + double rayDirY = data->dir_y + data->plane_y * cameraX; + + int mapX = (int)data->pos_x; + int mapY = (int)data->pos_y; + + double sideDistX, sideDistY; + double deltaDistX = fabs(1 / rayDirX); + double deltaDistY = fabs(1 / rayDirY); + double perpWallDist; + + int stepX, stepY; + int hit = 0; + int side; + + if (rayDirX < 0) { + stepX = -1; + sideDistX = (data->pos_x - mapX) * deltaDistX; + } else { + stepX = 1; + sideDistX = (mapX + 1.0 - data->pos_x) * deltaDistX; + } + if (rayDirY < 0) { + stepY = -1; + sideDistY = (data->pos_y - mapY) * deltaDistY; + } else { + stepY = 1; + sideDistY = (mapY + 1.0 - data->pos_y) * deltaDistY; + } + + while (hit == 0) { + if (sideDistX < sideDistY) { + sideDistX += deltaDistX; + mapX += stepX; + side = 0; + } else { + sideDistY += deltaDistY; + mapY += stepY; + side = 1; + } + if (worldMap[mapX][mapY] > 0) + hit = 1; + } + + if (side == 0) + perpWallDist = (mapX - data->pos_x + (1 - stepX) / 2) / rayDirX; + else + perpWallDist = (mapY - data->pos_y + (1 - stepY) / 2) / rayDirY; + + int lineHeight = (int)(WINDOW_HEIGHT / perpWallDist); + int drawStart = -lineHeight / 2 + WINDOW_HEIGHT / 2; + if(drawStart < 0) drawStart = 0; + int drawEnd = lineHeight / 2 + WINDOW_HEIGHT / 2; + if(drawEnd >= WINDOW_HEIGHT) drawEnd = WINDOW_HEIGHT - 1; + + int color; + if (side == 0 && stepX > 0) + color = 0x00FF0000; + else if (side == 0 && stepX < 0) + color = 0x0000FF00; + else if (side == 1 && stepY > 0) + color = 0x000000FF; + else + color = 0x00FFFF00; + + if (side == 1) color = (color >> 1) & 8355711; // Make sides darker + + for(int y = drawStart; y < drawEnd; y++) + my_mlx_pixel_put(data, x, y, color); + } + mlx_put_image_to_window(data->mlx, data->win, data->img, 0, 0); + return (0); +} + +int main(void) +{ + t_data data; + + data.mlx = mlx_init(); + data.win = mlx_new_window(data.mlx, WINDOW_WIDTH, WINDOW_HEIGHT, "Raycaster"); + data.img = mlx_new_image(data.mlx, WINDOW_WIDTH, WINDOW_HEIGHT); + data.addr = mlx_get_data_addr(data.img, &data.bits_per_pixel, &data.line_length, &data.endian); + + data.pos_x = 22; + data.pos_y = 12; + data.dir_x = -1; + data.dir_y = 0; + data.plane_x = 0; + data.plane_y = 0.66; + + mlx_hook(data.win, 2, 1L<<0, key_hook, &data); + mlx_loop_hook(data.mlx, render_frame, &data); + mlx_loop(data.mlx); + return (0); +} diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..f5ede6b --- /dev/null +++ b/test/test.h @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/27 12:07:20 by rparodi #+# #+# */ +/* Updated: 2024/11/27 12:08:19 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef TEST_H +# define TEST_H + +# include "minilibx-linux/mlx.h" +# include +# include +# include + +# define WINDOW_WIDTH 1024 +# define WINDOW_HEIGHT 768 +# define MAP_WIDTH 24 +# define MAP_HEIGHT 24 +# define MOVE_SPEED 0.5 +# define ROT_SPEED 0.5 + +typedef struct s_data +{ + void *mlx; + void *win; + void *img; + char *addr; + int bits_per_pixel; + int line_length; + int endian; + double pos_x; + double pos_y; + double dir_x; + double dir_y; + double plane_x; + double plane_y; +} t_data; + +#endif diff --git a/test/test2.c b/test/test2.c new file mode 100644 index 0000000..8992bd2 --- /dev/null +++ b/test/test2.c @@ -0,0 +1,262 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test2.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: rparodi +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/11/27 12:09:00 by rparodi #+# #+# */ +/* Updated: 2024/11/27 16:00:23 by rparodi ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minilibx-linux/mlx.h" +#include "test.h" + +int worldMap[MAP_WIDTH][MAP_HEIGHT] = {\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, \ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} \ +}; + +void my_mlx_pixel_put(t_data *data, int x, int y, int color) +{ + char *dst; + + dst = data->addr + (y * data->line_length + x * (data->bits_per_pixel / 8)); + *(unsigned int *)dst = color; +} + +void move_straight(t_data *data) +{ + if (!worldMap[\ + (int)(data->pos_x + data->dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x += data->dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y + data->dir_y * MOVE_SPEED)]) + data->pos_y += data->dir_y * MOVE_SPEED; +} + +void move_backward(t_data *data) +{ + if (!worldMap[\ + (int)(data->pos_x - data->dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x -= data->dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y - data->dir_y * MOVE_SPEED)]) + data->pos_y -= data->dir_y * MOVE_SPEED; +} + +void move_left(t_data *data) +{ + double perp_dir_x; + double perp_dir_y; + + perp_dir_x = -data->dir_y; + perp_dir_y = data->dir_x; + if (!worldMap[\ + (int)(data->pos_x + perp_dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x -= perp_dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y - perp_dir_y * MOVE_SPEED)]) + data->pos_y -= perp_dir_y * MOVE_SPEED; +} + +void move_right(t_data *data) +{ + double perp_dir_x; + double perp_dir_y; + + perp_dir_x = -data->dir_y; + perp_dir_y = data->dir_x; + if (!worldMap[\ + (int)(data->pos_x - perp_dir_x * MOVE_SPEED)][(int)data->pos_y]) + data->pos_x += perp_dir_x * MOVE_SPEED; + if (!worldMap[\ + (int)data->pos_x][(int)(data->pos_y + perp_dir_y * MOVE_SPEED)]) + data->pos_y += perp_dir_y * MOVE_SPEED; +} + +void look_left(t_data *data) +{ + double old_dir_x; + double old_plane_x; + + old_dir_x = data->dir_x; + old_plane_x = data->plane_x; + data->dir_x = data->dir_x * cos(ROT_SPEED) - data->dir_y * sin(ROT_SPEED); + data->dir_y = old_dir_x * sin(ROT_SPEED) + data->dir_y * cos(ROT_SPEED); + data->plane_x = data->plane_x * cos(ROT_SPEED) \ + - data->plane_y * sin(ROT_SPEED); + data->plane_y = old_plane_x * sin(ROT_SPEED) \ + + data->plane_y * cos(ROT_SPEED); +} + +void look_right(t_data *data) +{ + double old_dir_x; + double old_plane_x; + + old_dir_x = data->dir_x; + old_plane_x = data->plane_x; + data->dir_x = data->dir_x * cos(-ROT_SPEED) - data->dir_y * sin(-ROT_SPEED); + data->dir_y = old_dir_x * sin(-ROT_SPEED) + data->dir_y * cos(-ROT_SPEED); + data->plane_x = data->plane_x * cos(-ROT_SPEED) \ + - data->plane_y * sin(-ROT_SPEED); + data->plane_y = old_plane_x * sin(-ROT_SPEED) \ + + data->plane_y * cos(-ROT_SPEED); +} + +int key_hook(int keycode, t_data *data) +{ + if (keycode == 65307) + exit(0); + if (keycode == 119) + move_straight(data); + if (keycode == 115) + move_backward(data); + if (keycode == 97) + move_right(data); + if (keycode == 100) + move_left(data); + if (keycode == 65361) + look_left(data); + if (keycode == 65363) + look_right(data); + return (0); +} + +int render_frame(t_data *data) +{ + int y; + int x; + + y = 0; + while (y < WINDOW_HEIGHT) + { + x = 0; + while (x < WINDOW_WIDTH) + { + my_mlx_pixel_put(data, x, y, 0x00000000); + x++; + } + y++; + } + + for(int x = 0; x < WINDOW_WIDTH; x++) + { + double cameraX = 2 * x / (double)WINDOW_WIDTH - 1; + double rayDirX = data->dir_x + data->plane_x * cameraX; + double rayDirY = data->dir_y + data->plane_y * cameraX; + + int mapX = (int)data->pos_x; + int mapY = (int)data->pos_y; + + double sideDistX, sideDistY; + double deltaDistX = fabs(1 / rayDirX); + double deltaDistY = fabs(1 / rayDirY); + double perpWallDist; + + int stepX, stepY; + int hit = 0; + int side; + + if (rayDirX < 0) { + stepX = -1; + sideDistX = (data->pos_x - mapX) * deltaDistX; + } else { + stepX = 1; + sideDistX = (mapX + 1.0 - data->pos_x) * deltaDistX; + } + if (rayDirY < 0) { + stepY = -1; + sideDistY = (data->pos_y - mapY) * deltaDistY; + } else { + stepY = 1; + sideDistY = (mapY + 1.0 - data->pos_y) * deltaDistY; + } + + while (hit == 0) { + if (sideDistX < sideDistY) { + sideDistX += deltaDistX; + mapX += stepX; + side = 0; + } else { + sideDistY += deltaDistY; + mapY += stepY; + side = 1; + } + if (worldMap[mapX][mapY] > 0) + hit = 1; + } + + if (side == 0) + perpWallDist = (mapX - data->pos_x + (1 - stepX) / 2) / rayDirX; + else + perpWallDist = (mapY - data->pos_y + (1 - stepY) / 2) / rayDirY; + + int lineHeight = (int)(WINDOW_HEIGHT / perpWallDist); + int drawStart = -lineHeight / 2 + WINDOW_HEIGHT / 2; + if(drawStart < 0) drawStart = 0; + int drawEnd = lineHeight / 2 + WINDOW_HEIGHT / 2; + if(drawEnd >= WINDOW_HEIGHT) drawEnd = WINDOW_HEIGHT - 1; + + int color; + if (side == 0 && stepX > 0) + color = 0x00FF0000; + else if (side == 0 && stepX < 0) + color = 0x0000FF00; + else if (side == 1 && stepY > 0) + color = 0x000000FF; + else + color = 0x00FFFF00; + + for(int y = drawStart; y < drawEnd; y++) + my_mlx_pixel_put(data, x, y, color); + } + mlx_put_image_to_window(data->mlx, data->win, data->img, 0, 0); + return (0); +} + +int main(void) +{ + t_data data; + + data.mlx = mlx_init(); + data.win = mlx_new_window(data.mlx, WINDOW_WIDTH, WINDOW_HEIGHT, "Raycaster"); + data.img = mlx_new_image(data.mlx, WINDOW_WIDTH, WINDOW_HEIGHT); + data.addr = mlx_get_data_addr(data.img, &data.bits_per_pixel, &data.line_length, &data.endian); + + data.pos_x = 22; + data.pos_y = 12; + data.dir_x = -1; + data.dir_y = 0; + data.plane_x = 0; + data.plane_y = 0.66; + + mlx_hook(data.win, 2, 1L<<0, key_hook, &data); + mlx_loop_hook(data.mlx, render_frame, &data); + mlx_loop(data.mlx); + return (0); +} diff --git a/test/textures/a.xpm b/test/textures/a.xpm new file mode 100644 index 0000000..5d7ac8c --- /dev/null +++ b/test/textures/a.xpm @@ -0,0 +1,154 @@ +/* XPM */ +static char *_cb59dce4f574e3bd6a1e2f025c0312agi1mGDihwOOx8j7A[] = { +/* columns rows colors chars-per-pixel */ +"32 32 116 2 ", +" c #100F10", +". c #161515", +"X c #191717", +"o c #191718", +"O c #1E1C1C", +"+ c #211E1E", +"@ c #252222", +"# c #292626", +"$ c #2D2B2B", +"% c #322E2E", +"& c #3A2F2E", +"* c #36302F", +"= c #3C312E", +"- c #342F30", +"; c #353131", +": c #3A3434", +"> c #3D3836", +", c #3C3738", +"< c #3E3A3A", +"1 c #43332F", +"2 c #433534", +"3 c #4C3633", +"4 c #433A36", +"5 c #4C3937", +"6 c #433C3B", +"7 c #4B3D3B", +"8 c #503835", +"9 c #523D3C", +"0 c #46413E", +"q c #4B433D", +"w c #524433", +"e c #55443B", +"r c #453F41", +"t c #563D40", +"y c #474141", +"u c #4B4442", +"i c #4E4845", +"p c #4F4949", +"a c #544442", +"s c #584644", +"d c #534A42", +"f c #5A4A46", +"g c #554D4B", +"h c #5C4D4C", +"j c #545146", +"k c #56514C", +"l c #5B524D", +"z c #5D5552", +"x c #5F5A53", +"c c #614D46", +"v c #61534D", +"b c #625D4C", +"n c #625553", +"m c #635A53", +"M c #655B59", +"N c #695D5A", +"B c #636052", +"V c #696354", +"C c #6E6852", +"Z c #66615A", +"A c #6B625D", +"S c #6D695B", +"D c #70675F", +"F c #736A5D", +"G c #6C6360", +"H c #6B6463", +"J c #6F6563", +"K c #6D6865", +"L c #706763", +"P c #726766", +"I c #716A62", +"U c #726A63", +"Y c #756D63", +"T c #746A64", +"R c #786B66", +"E c #786D66", +"W c #716A68", +"Q c #746B69", +"! c #776E6C", +"~ c #7B6F69", +"^ c #796E6A", +"/ c #786E6C", +"( c #767161", +") c #7B7366", +"_ c #7C7367", +"` c #7E7A66", +"' c #767069", +"] c #79706B", +"[ c #7C716B", +"{ c #7F7868", +"} c #7F796C", +"| c #7E7572", +" . c #807D6D", +".. c #807776", +"X. c #837B70", +"o. c #847972", +"O. c #857C72", +"+. c #847B79", +"@. c #8A7F78", +"#. c #868172", +"$. c #898171", +"%. c #8C8673", +"&. c #8A8174", +"*. c #8D8870", +"=. c #8D867B", +"-. c #928B7C", +";. c #938C7D", +":. c #968F7F", +">. c #96907B", +",. c #98907F", +"<. c #8D8681", +"1. c #938C80", +"2. c #948C88", +"3. c #979081", +"4. c #999087", +"5. c #A29C81", +/* pixels */ +"V : H + Z m % - $ $ ' ! # -.$ k g x $ $ 2 &.$ % % 2 >.g ; z $ A ", +"&.d % $ 1 F 5.@ X.1 f [ % % % : z Y % ; O.L ] # @ N a T ; % , :.", +"A ; $ 6 = C $ , % , ; a $ I %.% 7 % o + 1 Z = 1 O % $ < @ & v L ", +"O ; T # 3 X @ 2 l z % % % g p % $ % A l $ ; : M t % = f G % # # ", +"e ; ; 6 > k $ & $ % @ % % : 4 % 0 % > T 4 $ % a % @ % $ 9 N $ -.", +"J % / z ~ 3.k , , f Z k e 3 # % O.d % % % } 6 : ; I | l $ , $ l ", +"N 8 2 2 3 O.m 6 , % E % = % 5 L E S % % 7 N J k = > u [ & D $ R ", +"= % + # ; % 2 % $ 7 l $ % : % : > $ $ $ , 2 q 4 % % % , , 4 % * ", +"$ h Z A $ % % 7 % : : $ A z q ; ; : ] I % ; $ ; D N 0 $ | Z z p ", +"M l g X.< 7 7 W u < % ; n { m , > > i > ; j % m q d g O 7 g g $ ", +"6 , n @ $ z : 2 % m .d % 9 % , l > ; ; m M @ : % , x @ $ % $ ; ", +"L 4 $ ; I <.u ; # A P A $ % # x 0 , % # z X.x < $ m P 9 = _ < g ", +"A 7 , + @.M & 9 % ; $ : % > % ; # ; % : n N n ; k % $ % G H % u ", +"$ % O.; $ $ . ` l % # $ # $ =.I 7 <.2.A ; % $ $ 6 x : , V Y > 6 ", +"2 ] [ s $ 9 @ E { m A O ] f A ; l s +.@ F I $ | / O.% % 2 0 $ : ", +"% % f a % $ ; A E = % # 3 i > $ $ , ..+ O g ; ~ N $ : : % $ 4 k ", +"$.j , < & #.% 6 : $ ;.a % 2 % g *.; g ; c v , $ : 6 T ~ % u ; ( ", +"g Z # : O.L ] # 6 N a T # % , D p d % % = F ` ; Z = f [ , % $ u ", +"v % @ # 1 Z = 1 $ % $ ; 6 % v l A @ @ ; & j $ ; # $ ; a . I S : ", +"# $ g l $ $ , M t % = f G , ; $ ; # z , 2 6 # 7 L ~ ; 7 % u 6 ; ", +") % 0 z e , # a % ; % # 9 N $ -.n , < 6 > k $ & $ % $ # % < 4 $ ", +": : ; $ % } b d , I | l $ $ # l W % / z ~ 3.S ; * f #.S e 3 ; * ", +"0 6 % p s N J k = > J [ & D @ R N 8 3 9 3 O.m ; # % E % 2 % 9 A ", +"v $ $ $ , : 4 : % * ; % 6 4 % % % % O < % % 2 % % > D @ ; q % z ", +"# 2 ] z % , % # l N 0 # | +.4.p % q O.A $ r # a ; w = , A g m o ", +"( i 0 c 7 j % ] l 6 , % 2 G N % > J A o.# 7 a W Q A + n k [ % ", +"k M 9 @ S M # 2 $ 6 ] , # % % % % % n # # Q * 2 % d .d < 9 % ; ", +"u u # $ Z 1.Z % % m P 9 = _ @ A x % $ ; I <.L $ $ g P ~ % % y [ ", +"p $ % : u g a $ D % $ % G H % A y : ; % @.M 2 9 $ % # 3 @ f ; $ ", +"7 K z y % # ; % 6 ] 7 , V ,.d 6 % % O.% $ ; % B ; % y ; ; $ =.I ", +"J 7 g < u I $ M x O.% # 7 Z ; 1 9 ] [ s $ 2 # 6 { i q O ] f A , ", +"u ; .., ; A u ~ N $ ; $ + $ 1 l % % f a , % # A z % % $ 3 n 9 % " +}; diff --git a/test/textures/b.xpm b/test/textures/b.xpm new file mode 100644 index 0000000..99258e6 --- /dev/null +++ b/test/textures/b.xpm @@ -0,0 +1,49 @@ +/* XPM */ +static char *_947bb94b4e04fd3d8b6e97faaaaa774DMhsGHANfMg9UIKL[] = { +/* columns rows colors chars-per-pixel */ +"32 32 11 1 ", +" c #422816", +". c #4E371C", +"X c #584529", +"o c #655131", +"O c #665232", +"+ c #655339", +"@ c #705C41", +"# c #756349", +"$ c #796442", +"% c #816D54", +"& c #948066", +/* pixels */ +"##++XX#@###%@%%O@X++.X#@@XX+++++", +"#@o+X #%##@O+X@@++XX+++@+@@++#%", +"#%#OO.+XXo+%#&%##.X.X##%@@@++##O", +"oooXXXX. +@@OX#.X##+X+..+#@O@X++", +"+OX@O@%%##@XX++OooXXX.X+XXX+@OXX", +"$X#O@.X@XXX.+.XX..+XX+XX+@+X....", +"#+%%++X+@@@X++#+X..+@+#####%#$#@", +"+X+X...XX@#.+#X@@+.++#&%@@@#+.++", +"X+XXX+XXXX@#%.@##@@.@++++#X.X.@%", +".+XX..X+@@++..#@++...X.XXX+@+XX+", +"X+X@#%+X.X++#+X XX++++...++X+X+", +"X..++@.XXXXOO@@@&##%@@+...++.++X", +"+@+X...#@#%@+@@+@#+X@#++@X.+@#++", +"X.XXX++&+@++X+.X+++X+XX###@@@X+X", +" .#++###+%#@+X#oXX+@@#@+@##+##..", +".%@##XOX%#@.@@X..X.X@@+@@@@@XX++", +"#@#X.XXXX+++.XX@#+++X XXX#+X+X+&", +"X@#%+X@XX.XX++O##@+..X++@#@%%++@", +"##@##.@+XXXX.XX@XX+X..+XX@#%%#@X", +"..X##.+X+@XX++@++X++.+X++++X+++.", +"+#+.XX+XX#+%&#@@@#X XX@XX.XX# .+", +"XX+X.+%%%%@@XX++%+%&%#++.X+X@.XX", +"# ++@+@#+XX.+X##+X##+@++@+@@#%", +"##X+X+@oX@....XXXX+o+#@@@++ X#X@", +"%+@XX..XX.X#..@X+X++#+XX+.@X+X%@", +"+X.X.X+++#XX+XX@@@@#+++.+++@+%OX", +"XOX+@X+@+@@+++X+++X+@X+++@X@X+X ", +"@##&@#++++@+++@X+. ..++@@.X++X+%", +"@#@#X+@++X@+XXXX++@+@XXX.X+@@@@%", +"XXOXXX...+@@#@@X@@#@#@&...X@#@.X", +"XX@...+@%&#XX@XX++@ .@@#@@+@X.X+", +"%@.@%@@+++@o++++X+X+@++XXO@@@%#&" +};