/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/08 14:14:02 by dkaiser #+# #+# */
-/* Updated: 2024/05/29 15:57:34 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 16:38:06 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
t_vector direction;
t_vector velocity;
t_ivector size;
+ int steps;
mlx_image_t *img;
} t_actor;
{
t_ivector grid_size;
t_ivector tile_size;
- char *tiles;
+ char *tiles;
t_ivector player_start_tile;
t_ivector exit_tile;
mlx_image_t *collectible_img;
int load_map_from_file(t_tilemap *tilemap, char *filename);
int check_map(t_tilemap *map);
-int check_for_valid_path(t_tilemap *map);
+int check_for_valid_path(t_tilemap *map);
int init(t_game *game);
void loop(void *params);
void player_process(t_game *game);
-int draw(t_game *game);
-int draw_walls(t_game *game);
-void draw_exit(t_game *game);
+void draw(t_game *game);
+void draw_map(t_game *game);
void on_key_input(mlx_key_data_t event, void *params);
t_vector grid_to_screen_pos(t_ivector grid_pos, t_ivector tile_size);
t_ivector screen_to_grid_pos(t_vector screen_pos, t_ivector tile_size);
int check_collision(t_collider a, t_collider b);
int check_map_collision(t_collider collider, t_tilemap *map,
enum e_tile type);
-void move_and_slide(t_actor *actor, t_tilemap *map,
+int move_and_slide(t_actor *actor, t_tilemap *map,
double delta_time);
int is_on_floor(t_collider collider, t_tilemap *map);
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/29 15:54:52 by dkaiser #+# #+# */
-/* Updated: 2024/05/29 16:32:26 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 16:03:06 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
#include "so_long.h"
-static void floodfill(char *tiles, t_ivector size, t_ivector pos);
-static int check_tiles(char *tiles, int size);
+static void floodfill(char *tiles, t_ivector size, t_ivector pos);
+static int check_tiles(char *tiles, int size);
-int check_for_valid_path(t_tilemap *map)
+int check_for_valid_path(t_tilemap *map)
{
- char *tiles;
+ char *tiles;
- tiles = malloc(map->grid_size.x * map->grid_size.y);
- if (!tiles)
- return (1); // TODO: Error
- ft_strlcpy(tiles, map->tiles, map->grid_size.x * map->grid_size.y + 1);
- floodfill(tiles, map->grid_size, map->player_start_tile);
- return (check_tiles(tiles, map->grid_size.x * map->grid_size.y));
+ tiles = malloc(map->grid_size.x * map->grid_size.y);
+ if (!tiles)
+ {
+ ft_putstr_fd("Allocation error\n", 1);
+ return (1);
+ }
+ ft_strlcpy(tiles, map->tiles, map->grid_size.x * map->grid_size.y + 1);
+ floodfill(tiles, map->grid_size, map->player_start_tile);
+ return (check_tiles(tiles, map->grid_size.x * map->grid_size.y));
}
-static void floodfill(char *tiles, t_ivector size, t_ivector pos)
+static void floodfill(char *tiles, t_ivector size, t_ivector pos)
{
- if (tiles[pos.y * size.x + pos.x] == WALL || tiles[pos.y * size.x + pos.x] == 'X')
- return ;
- tiles[pos.y * size.x + pos.x] = 'X';
- floodfill(tiles, size, (t_ivector){pos.x - 1, pos.y});
- floodfill(tiles, size, (t_ivector){pos.x + 1, pos.y});
- floodfill(tiles, size, (t_ivector){pos.x, pos.y - 1});
- floodfill(tiles, size, (t_ivector){pos.x, pos.y + 1});
+ if (tiles[pos.y * size.x + pos.x] == WALL)
+ return ;
+ if (tiles[pos.y * size.x + pos.x] == 'X')
+ return ;
+ tiles[pos.y * size.x + pos.x] = 'X';
+ floodfill(tiles, size, (t_ivector){pos.x - 1, pos.y});
+ floodfill(tiles, size, (t_ivector){pos.x + 1, pos.y});
+ floodfill(tiles, size, (t_ivector){pos.x, pos.y - 1});
+ floodfill(tiles, size, (t_ivector){pos.x, pos.y + 1});
}
-static int check_tiles(char *tiles, int size)
+static int check_tiles(char *tiles, int size)
{
- int i;
+ int i;
- i = 0;
- while (i < size)
- {
- if (tiles[i] != WALL && tiles[i] != 'X')
- return (1);
- i++;
- }
- return (0);
+ i = 0;
+ while (i < size)
+ {
+ if (tiles[i] != WALL && tiles[i] != 'X')
+ return (1);
+ i++;
+ }
+ return (0);
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/14 11:48:59 by dkaiser #+# #+# */
-/* Updated: 2024/05/15 15:19:54 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 15:43:32 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
{
check_tile.x = local_tile.x + x;
check_tile.y = local_tile.y + y;
- result |= check_map_collision_for_tile(collider, map, check_tile, type);
+ result |= check_map_collision_for_tile(collider, map, check_tile,
+ type);
y++;
}
x++;
return (0);
}
-void move_and_slide(t_actor *actor, t_tilemap *map, double delta_time)
+int move_and_slide(t_actor *actor, t_tilemap *map, double delta_time)
{
t_collider c;
+ int is_moving;
+ is_moving = 0;
c.size = actor->size;
c.position.x = actor->position.x + (actor->velocity.x * delta_time);
c.position.y = actor->position.y;
if ((check_map_collision(c, map, WALL) & (RIGHT | LEFT)) == 0)
+ {
actor->position.x = c.position.x;
+ is_moving += (actor->direction.x != 0);
+ }
else
actor->velocity.x = 0;
c.position.x = actor->position.x;
c.position.y = actor->position.y + (actor->velocity.y * delta_time);
if ((check_map_collision(c, map, WALL) & (UP | DOWN)) == 0)
+ {
actor->position.y = c.position.y;
+ is_moving += (actor->direction.y != 0);
+ }
else
actor->velocity.y = 0;
+ return (is_moving != 0);
}
int is_on_floor(t_collider collider, t_tilemap *map)
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/09 17:58:23 by dkaiser #+# #+# */
-/* Updated: 2024/05/20 20:10:15 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 16:37:51 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
#include "libft.h"
#include "so_long.h"
-int draw(t_game *game)
+static void draw_walls_and_collectibles(t_game *game);
+static void setup_images(t_game *game, mlx_image_t **wall_image);
+static void draw_exit(t_game *game);
+
+void draw(t_game *game)
{
game->player.img->instances[0].x = game->player.position.x;
game->player.img->instances[0].y = game->player.position.y;
- return (0);
}
-void draw_exit(t_game *game)
+void draw_map(t_game *game)
{
- mlx_texture_t *exit_texture;
- mlx_image_t *exit_image;
- t_vector pos;
-
- exit_texture = mlx_load_png("textures/exit.png");
- exit_image = mlx_texture_to_image(game->mlx, exit_texture);
- mlx_resize_image(exit_image, game->map.tile_size.x, game->map.tile_size.y);
- pos = grid_to_screen_pos(game->map.exit_tile, game->map.tile_size);
- mlx_image_to_window(game->mlx, exit_image, pos.x, pos.y);
+ draw_walls_and_collectibles(game);
+ draw_exit(game);
}
-int draw_walls(t_game *game)
+static void draw_walls_and_collectibles(t_game *game)
{
- int x;
- int y;
- mlx_texture_t *wall_texture;
- mlx_image_t *wall_image;
- mlx_texture_t *collectible_texture;
+ int x;
+ int y;
+ mlx_image_t *wall_image;
- wall_texture = mlx_load_png("textures/wall.png");
- wall_image = mlx_texture_to_image(game->mlx, wall_texture);
- collectible_texture = mlx_load_png("textures/collectible.png");
- game->map.collectible_img = mlx_texture_to_image(game->mlx, collectible_texture);
- mlx_resize_image(wall_image, 48, 48);
- mlx_resize_image(game->map.collectible_img, 48, 48);
- game->map.tile_size.x = 48;
- game->map.tile_size.y = 48;
+ setup_images(game, &wall_image);
x = 0;
while (x < game->map.grid_size.x)
{
}
x++;
}
- return (0);
+}
+
+static void setup_images(t_game *game, mlx_image_t **wall_image)
+{
+ mlx_texture_t *wall_texture;
+ mlx_texture_t *collectible_texture;
+
+ wall_texture = mlx_load_png("textures/wall.png");
+ *wall_image = mlx_texture_to_image(game->mlx, wall_texture);
+ collectible_texture = mlx_load_png("textures/collectible.png");
+ game->map.collectible_img = mlx_texture_to_image(game->mlx,
+ collectible_texture);
+ mlx_resize_image(*wall_image, 48, 48);
+ mlx_resize_image(game->map.collectible_img, 48, 48);
+}
+
+static void draw_exit(t_game *game)
+{
+ mlx_texture_t *exit_texture;
+ mlx_image_t *exit_image;
+ t_vector pos;
+
+ exit_texture = mlx_load_png("textures/exit.png");
+ exit_image = mlx_texture_to_image(game->mlx, exit_texture);
+ mlx_resize_image(exit_image, game->map.tile_size.x, game->map.tile_size.y);
+ pos = grid_to_screen_pos(game->map.exit_tile, game->map.tile_size);
+ mlx_image_to_window(game->mlx, exit_image, pos.x, pos.y);
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/09 14:50:09 by dkaiser #+# #+# */
-/* Updated: 2024/05/29 16:16:13 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 15:55:28 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
{
game->input_direction = ZERO;
game->map.tile_size = (t_ivector){48, 48};
- game->mlx = mlx_init(game->map.grid_size.x * game->map.tile_size.x, game->map.grid_size.y * game->map.tile_size.y, "so_long", false);
+ game->mlx = mlx_init(game->map.grid_size.x * game->map.tile_size.x,
+ game->map.grid_size.y * game->map.tile_size.y, "so_long", false);
init_hooks(game);
init_player(game);
return (0);
game->map.tile_size);
player->velocity = (t_vector){0, 0};
player->size = (t_ivector){44, 44};
+ player->steps = 0;
+ ft_printf("Steps: %d\n", game->player.steps);
player->img = mlx_texture_to_image(game->mlx, texture);
mlx_resize_image(player->img, player->size.x, player->size.y);
mlx_image_to_window(game->mlx, player->img, player->position.x,
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/09 15:37:40 by dkaiser #+# #+# */
-/* Updated: 2024/05/10 12:13:22 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 15:58:43 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
+#include "MLX42/MLX42.h"
#include "so_long.h"
+static void on_key_press(t_game *game, mlx_key_data_t event);
+static void on_key_release(t_game *game, mlx_key_data_t event);
+
void on_key_input(mlx_key_data_t event, void *params)
{
t_game *game;
game = (t_game *)params;
- if (event.action == MLX_PRESS)
- {
- if (event.key == MLX_KEY_W || event.key == MLX_KEY_UP)
- game->input_direction |= UP;
- else if (event.key == MLX_KEY_A || event.key == MLX_KEY_LEFT)
- game->input_direction |= LEFT;
- else if (event.key == MLX_KEY_S || event.key == MLX_KEY_DOWN)
- game->input_direction |= DOWN;
- else if (event.key == MLX_KEY_D || event.key == MLX_KEY_RIGHT)
- game->input_direction |= RIGHT;
- }
+ if (event.key == MLX_KEY_ESCAPE && event.action == MLX_PRESS)
+ mlx_close_window(game->mlx);
+ else if (event.action == MLX_PRESS)
+ on_key_press(game, event);
else if (event.action == MLX_RELEASE)
- {
- if (event.key == MLX_KEY_W || event.key == MLX_KEY_UP)
- game->input_direction &= ~UP;
- else if (event.key == MLX_KEY_A || event.key == MLX_KEY_LEFT)
- game->input_direction &= ~LEFT;
- else if (event.key == MLX_KEY_S || event.key == MLX_KEY_DOWN)
- game->input_direction &= ~DOWN;
- else if (event.key == MLX_KEY_D || event.key == MLX_KEY_RIGHT)
- game->input_direction &= ~RIGHT;
- }
+ on_key_release(game, event);
+}
+
+static void on_key_press(t_game *game, mlx_key_data_t event)
+{
+ if (event.key == MLX_KEY_W || event.key == MLX_KEY_UP)
+ game->input_direction |= UP;
+ else if (event.key == MLX_KEY_A || event.key == MLX_KEY_LEFT)
+ game->input_direction |= LEFT;
+ else if (event.key == MLX_KEY_S || event.key == MLX_KEY_DOWN)
+ game->input_direction |= DOWN;
+ else if (event.key == MLX_KEY_D || event.key == MLX_KEY_RIGHT)
+ game->input_direction |= RIGHT;
+}
+
+static void on_key_release(t_game *game, mlx_key_data_t event)
+{
+ if (event.key == MLX_KEY_W || event.key == MLX_KEY_UP)
+ game->input_direction &= ~UP;
+ else if (event.key == MLX_KEY_A || event.key == MLX_KEY_LEFT)
+ game->input_direction &= ~LEFT;
+ else if (event.key == MLX_KEY_S || event.key == MLX_KEY_DOWN)
+ game->input_direction &= ~DOWN;
+ else if (event.key == MLX_KEY_D || event.key == MLX_KEY_RIGHT)
+ game->input_direction &= ~RIGHT;
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/09 15:09:24 by dkaiser #+# #+# */
-/* Updated: 2024/05/14 12:45:26 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 15:43:17 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
game = (t_game *)params;
player_process(game);
+ if (game->player.steps)
+ ft_printf("\e[1A\e[KSteps: %d\n", game->player.steps);
draw(game);
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/08 14:14:13 by dkaiser #+# #+# */
-/* Updated: 2024/05/29 14:58:22 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 16:37:21 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
+#include "libft.h"
#include "so_long.h"
+static void cleanup(t_game *game);
+static int error(char *msg);
+
int main(int argc, char *argv[])
{
t_game game;
if (argc != 2)
- return (1);
+ return (error("Usage: ./so_long <map>"));
if (load_map_from_file(&game.map, argv[1]))
- return (1);
+ return (error("Not a valid map."));
if (check_map(&game.map))
- return (1);
+ {
+ free(game.map.tiles);
+ return (error("Not a valid map."));
+ }
init(&game);
- draw_walls(&game);
- draw_exit(&game);
+ draw_map(&game);
mlx_loop(game.mlx);
+ cleanup(&game);
+}
+
+static void cleanup(t_game *game)
+{
+ if (game->map.tiles)
+ free(game->map.tiles);
+ if (game->mlx)
+ mlx_terminate(game->mlx);
+}
+
+static int error(char *msg)
+{
+ ft_putendl_fd("Error", 2);
+ ft_putendl_fd(msg, 2);
+ return (1);
}
/* By: dkaiser <dkaiser@student.42heilbronn.de +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/14 12:40:05 by dkaiser #+# #+# */
-/* Updated: 2024/05/29 13:15:08 by dkaiser ### ########.fr */
+/* Updated: 2024/06/10 16:28:09 by dkaiser ### ########.fr */
/* */
/* ************************************************************************** */
+#include "MLX42/MLX42.h"
#include "ft_printf.h"
#include "so_long.h"
static t_vector get_direction_from_input(t_game *game);
static void handle_collectible_collision(t_actor *player, t_tilemap *map);
static void collect_collectible(t_ivector pos, t_tilemap *map);
-static void handle_exit_collision(t_actor *player, t_tilemap *map);
+static void handle_exit_collision(t_game *game);
void player_process(t_game *game)
{
player->velocity.x = player->direction.x * PLAYER_MOVE_SPEED;
player->velocity.y = player->direction.y * PLAYER_MOVE_SPEED;
handle_collectible_collision(player, &game->map);
- handle_exit_collision(player, &game->map);
- move_and_slide(player, &game->map, game->mlx->delta_time);
+ handle_exit_collision(game);
+ if (move_and_slide(player, &game->map, game->mlx->delta_time))
+ player->steps++;
}
static void handle_collectible_collision(t_actor *player, t_tilemap *map)
static void collect_collectible(t_ivector pos, t_tilemap *map)
{
- size_t i;
- t_vector collectible_pos;
- t_ivector collectible_tile;
+ size_t i;
+ t_vector collectible_pos;
+ t_ivector collectible_tile;
- ft_printf("Collected a collectile.\n");
set_tile(map, pos.x, pos.y, EMPTY);
i = 0;
while (i < map->collectible_img->count)
}
}
-static void handle_exit_collision(t_actor *player, t_tilemap *map)
+static void handle_exit_collision(t_game *game)
{
t_collider player_collider;
- size_t i;
+ size_t i;
+ t_actor *player;
+ t_tilemap *map;
+ player = &game->player;
+ map = &game->map;
player_collider = (t_collider){player->position, player->size};
if (check_map_collision(player_collider, map, EXIT))
{
return ;
i++;
}
- exit(0);
+ mlx_close_window(game->mlx);
}
}