feat: loots of things!!! *

Added features:
- Check if the room is valid
- Pathfinding
- Firsk
- Camera
Changes:
- Borders
Dev:
- new test rooms
- ber.vim plugin
This commit is contained in:
mcolonna 2024-04-15 19:23:58 +02:00
parent b7a2d0494f
commit 9e81a59a7e
95 changed files with 8342 additions and 147 deletions

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/26 16:27:06 by mcolonna #+# #+# */
/* Updated: 2024/04/05 18:44:23 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 16:21:00 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -19,7 +19,8 @@ const t_assetmeta g_assetsmap[NB_ASSETS] = {
{"floor/1", 50, 100, 50, 100, true},
{"floor/2", 50, 100, 50, 100, true},
// WALL
{"wall/border", 50, 100, 50, 100, true},
{"wall/border_top", 50, 100, 50, 100, true},
{"wall/border_bottom", 50, 100, 50, 100, true},
{"wall/inner", 50, 100, 30, 100, false},
// OBJECTS
// snas
@ -39,11 +40,6 @@ const t_assetmeta g_assetsmap[NB_ASSETS] = {
{"object/snas/walk_up_2", 50, 100, 30, 100, false},
{"object/snas/walk_up_3", 50, 100, 30, 100, false},
{"object/snas/walk_up_4", 50, 100, 30, 100, false},
// firsk
{"object/firsk/down", 50, 110, 30, 100, false},
{"object/firsk/up", 40, 100, 30, 100, false},
{"object/firsk/left", 50, 100, 30, 100, false},
{"object/firsk/right", 50, 110, 30, 100, false},
// ketchup
{"object/ketchup/still/1", 50, 100, 40, 110, false},
{"object/ketchup/still/2", 50, 100, 40, 110, false},
@ -69,5 +65,22 @@ const t_assetmeta g_assetsmap[NB_ASSETS] = {
{"object/exit/using2/4", 50, 100, 50, 100, false},
{"object/exit/using2/5", 50, 100, 50, 100, false},
{"object/exit/using2/6", 50, 100, 50, 100, false},
{"object/exit/using2/7", 50, 100, 50, 100, false}
{"object/exit/using2/7", 50, 100, 50, 100, false},
// firsk
{"object/firsk/down", 50, 110, 30, 100, false},
{"object/firsk/up", 40, 100, 30, 100, false},
{"object/firsk/left", 50, 100, 30, 100, false},
{"object/firsk/right", 50, 110, 30, 100, false},
{"object/firsk/walk_down_1", 50, 110, 30, 100, false},
{"object/firsk/walk_down_2", 50, 110, 30, 100, false},
{"object/firsk/walk_down_3", 50, 110, 30, 100, false},
{"object/firsk/walk_down_4", 50, 110, 30, 100, false},
{"object/firsk/walk_right_1", 50, 110, 30, 100, false},
{"object/firsk/walk_right_2", 50, 110, 30, 100, false},
{"object/firsk/walk_left_1", 50, 100, 30, 100, false},
{"object/firsk/walk_left_2", 50, 100, 30, 100, false},
{"object/firsk/walk_up_1", 40, 100, 30, 100, false},
{"object/firsk/walk_up_2", 40, 100, 30, 100, false},
{"object/firsk/walk_up_3", 40, 100, 30, 100, false},
{"object/firsk/walk_up_4", 40, 100, 30, 100, false},
};

View file

@ -6,14 +6,15 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/11 16:02:29 by mcolonna #+# #+# */
/* Updated: 2024/04/08 15:33:56 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 16:22:17 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
const t_spritemeta g_spritesmap[NB_SPRITES] = {
{WALL_BORDER, 50, 50, ANIMATION, 1, 1},
{WALL_BORDER_TOP, 50, 50, ANIMATION, 1, 1},
{WALL_BORDER_BOTTOM, 50, 50, ANIMATION, 1, 1},
{FLOOR_1, 50, 50, ANIMATION, 1, 1},
{FLOOR_2, 50, 50, ANIMATION, 1, 1},
{OBJECT_SNAS, 50, 50, CHARACTER_STILL, 0, 0},
@ -27,4 +28,9 @@ const t_spritemeta g_spritesmap[NB_SPRITES] = {
{OBJECT_EXIT_INACTIVE_1, 50, 50, ANIMATION, 2, 4},
{OBJECT_EXIT_ACTIVE_1, 50, 50, ANIMATION, 4, 2},
{OBJECT_EXIT_USING1_1, 50, 50, ANIMATION_ONCE, 11, 1},
{OBJECT_FIRSK, 50, 50, CHARACTER_STILL, 0, 0},
{OBJECT_FIRSK_WALK_DOWN_1, 50, 50, ANIMATION, 4, 3},
{OBJECT_FIRSK_WALK_UP_1, 50, 50, ANIMATION, 4, 3},
{OBJECT_FIRSK_WALK_RIGHT_1, 50, 50, ANIMATION, 2, 3},
{OBJECT_FIRSK_WALK_LEFT_1, 50, 50, ANIMATION, 2, 3},
};

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/26 15:05:30 by mcolonna #+# #+# */
/* Updated: 2024/04/02 17:43:34 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 17:22:45 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -33,28 +33,28 @@ static inline void add_color(t_pixel *dest, t_pixel src)
>> 8;
}
static inline t_imglimits get_limits(int x, int y, t_image img)
static inline t_imglimits get_limits(t_point p, t_image img)
{
t_imglimits r;
r.xmin = -x;
r.xmin = -p.x;
if (img.asset.limit_left > r.xmin)
r.xmin = img.asset.limit_left;
r.xmax = WINDOW_WIDTH - x;
r.xmax = WINDOW_WIDTH - p.x;
if (img.asset.limit_right < r.xmax)
r.xmax = img.asset.limit_right;
r.ymin = -y;
r.ymin = -p.y;
if (img.asset.limit_up > r.ymin)
r.ymin = img.asset.limit_up;
r.ymax = WINDOW_HEIGHT - y;
r.ymax = WINDOW_HEIGHT - p.y;
if (img.asset.limit_down < r.ymax)
r.ymax = img.asset.limit_down;
return (r);
}
static inline void display_draw_alpha(int x, int y, t_image img)
static inline void display_draw_alpha(t_point p, t_image img)
{
const t_imglimits limits = get_limits(x, y, img);
const t_imglimits limits = get_limits(p, img);
int img_x;
int img_y;
@ -65,7 +65,7 @@ static inline void display_draw_alpha(int x, int y, t_image img)
while (img_x < limits.xmax)
{
add_color(
&g_screenbuf.data[(y + img_y) * WINDOW_WIDTH + (x + img_x)],
&g_screenbuf.data[(p.y + img_y) * WINDOW_WIDTH + (p.x + img_x)],
img.data[img_y * img.width + img_x]);
img_x++;
}
@ -73,9 +73,9 @@ static inline void display_draw_alpha(int x, int y, t_image img)
}
}
static inline void display_draw_opaque(int x, int y, t_image img)
static inline void display_draw_opaque(t_point p, t_image img)
{
const t_imglimits limits = get_limits(x, y, img);
const t_imglimits limits = get_limits(p, img);
int img_x;
int img_y;
@ -85,7 +85,7 @@ static inline void display_draw_opaque(int x, int y, t_image img)
img_x = limits.xmin;
while (img_x < limits.xmax)
{
g_screenbuf.data[(y + img_y) * WINDOW_WIDTH + (x + img_x)]
g_screenbuf.data[(p.y + img_y) * WINDOW_WIDTH + (p.x + img_x)]
= img.data[img_y * img.width + img_x];
img_x++;
}
@ -93,12 +93,12 @@ static inline void display_draw_opaque(int x, int y, t_image img)
}
}
void display_draw(int x, int y, t_assetsmap_id asset)
void display_draw(t_point p, t_assetsmap_id asset)
{
const t_image img = g_allassets[asset];
if (img.asset.opaque)
display_draw_opaque(x, y, img);
display_draw_opaque(p, img);
else
display_draw_alpha(x, y, img);
display_draw_alpha(p, img);
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/07 22:28:52 by mcolonna #+# #+# */
/* Updated: 2024/04/03 15:56:09 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 17:24:03 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -21,12 +21,12 @@ t_sprite sprite_init(t_spritesmap_id id)
return (r);
}
bool sprite_draw(int x, int y, t_sprite *spr)
bool sprite_draw(t_point p, t_sprite *spr)
{
if (spr->meta->type == ANIMATION || spr->meta->type == ANIMATION_ONCE)
{
display_draw(
x - spr->meta->origin_x, y - spr->meta->origin_y,
point_init(p.x - spr->meta->origin_x, p.y - spr->meta->origin_y),
spr->meta->first_frame + spr->index / spr->meta->delay_frame);
spr->index++;
if (spr->index >= spr->meta->nb_frames * spr->meta->delay_frame)
@ -38,7 +38,7 @@ bool sprite_draw(int x, int y, t_sprite *spr)
}
else
display_draw(
x - spr->meta->origin_x, y - spr->meta->origin_y,
point_init(p.x - spr->meta->origin_x, p.y - spr->meta->origin_y),
spr->meta->first_frame + spr->index);
return (true);
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/02/26 15:28:34 by mcolonna #+# #+# */
/* Updated: 2024/04/09 14:46:08 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 17:57:05 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */

73
src/room/camera.c Normal file
View file

@ -0,0 +1,73 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* camera.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/11 16:34:56 by mcolonna #+# #+# */
/* Updated: 2024/04/15 18:09:36 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
static t_point find_snas_position(void)
{
const t_room room = g_env.room;
t_point pos;
t_object *obj;
t_character character;
pos.y = -1;
while (++pos.y < room.height)
{
pos.x = -1;
while (++pos.x < room.width)
{
obj = room.objects[pos.y * room.width + pos.x];
if (obj && obj->type.init == snas_init)
{
character = ((t_snas_data *)obj->data)->character;
return (point_subpoint(point_add(point_multiply(pos, 50), 25),
point_multiply(point_fromdirection(character.direction),
character.walk_remaining_steps * 50
/ character.walk_steps_nb
)));
}
}
}
error_err("snas is nowhere");
return (point_init(0, 0));
}
static void limit(int *n, int min, int max)
{
if (*n < min)
*n = min;
if (*n > max)
*n = max;
}
void camera_sync(void)
{
const t_point obj_pos = find_snas_position();
const t_point room_dims = point_multiply(
point_init(g_env.room.width, g_env.room.height), 50);
t_point *const camera_pos = &g_env.camera.pos;
if (room_dims.x <= WINDOW_WIDTH)
camera_pos->x = -(WINDOW_WIDTH - room_dims.x) / 2;
else
{
camera_pos->x = obj_pos.x - WINDOW_WIDTH / 2;
limit(&camera_pos->x, 0, room_dims.x - WINDOW_WIDTH);
}
if (room_dims.y <= WINDOW_HEIGHT)
camera_pos->y = -(WINDOW_HEIGHT - room_dims.y) / 2;
else
{
camera_pos->y = obj_pos.y - WINDOW_HEIGHT / 2;
limit(&camera_pos->y, 0, room_dims.y - WINDOW_HEIGHT);
}
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/15 15:27:03 by mcolonna #+# #+# */
/* Updated: 2024/04/05 19:44:45 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 18:00:53 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -35,21 +35,18 @@ static void character_initstate(t_character *character)
}
}
void character_draw(t_character *character, int x, int y)
void character_draw(t_character *character, t_point pos)
{
t_point pos;
pos = point_init(x, y);
point_addto(&pos,
point_multiply(
point_fromdirection(character->direction),
character->walk_remaining_steps * 50 / -WALK_STEPS_NB
character->walk_remaining_steps * 50 / -character->walk_steps_nb
));
sprite_draw(pos.x, pos.y, &character->spr);
sprite_draw(pos, &character->spr);
}
t_point character_loop(
t_character *character, t_point pos, t_direction (*brain)(void))
t_character *character, t_point pos, t_direction (*brain)(t_point pos))
{
t_direction move;
@ -61,13 +58,13 @@ t_point character_loop(
}
else
{
move = brain();
move = brain(pos);
if (move != NO_DIRECTION)
{
character->direction = move;
if (room_canwalk(g_env.room, character, pos))
{
character->walk_remaining_steps = WALK_STEPS_NB - 1;
character->walk_remaining_steps = character->walk_steps_nb - 1;
character_initstate(character);
return (point_fromdirection(character->direction));
}
@ -77,12 +74,13 @@ t_point character_loop(
return (point_init(0, 0));
}
t_character character_init(t_character_sprites *sprites)
t_character character_init(t_character_sprites *sprites, int walk_steps_nb)
{
t_character r;
r.direction = DOWN;
r.sprites = sprites;
r.walk_steps_nb = walk_steps_nb;
r.walk_remaining_steps = 0;
r.spr = sprite_init(r.sprites->still);
character_initstate(&r);

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/08 15:01:16 by mcolonna #+# #+# */
/* Updated: 2024/04/09 14:35:20 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 17:43:20 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -25,11 +25,11 @@ static t_point exit_loop(t_object *obj, t_point pos)
return (point_init(0, 0));
}
static void exit_draw(t_object *obj, int x, int y)
static void exit_draw(t_object *obj, t_point p)
{
t_exit_data *const data = (t_exit_data *)(obj->data);
sprite_draw(x, y, &data->spr);
sprite_draw(p, &data->spr);
}
static bool exit_walk_through(
@ -47,7 +47,7 @@ static bool exit_walk_through(
t_object exit_init(t_memclass mc)
{
static const t_objecttype type
= {init: exit_init, loop: exit_loop, draw: exit_draw,
= {solid: true, init: exit_init, loop: exit_loop, draw: exit_draw,
walk_through: exit_walk_through};
t_object r;
t_exit_data *data;

56
src/room/object_firsk.c Normal file
View file

@ -0,0 +1,56 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* object_firsk.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/11 13:55:04 by mcolonna #+# #+# */
/* Updated: 2024/04/15 18:01:36 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
static t_direction firsk_brain(t_point pos)
{
return (pathfinding(pos, room_find(snas_init)));
}
static t_point firsk_loop(t_object *obj, t_point pos)
{
t_point r;
r = character_loop(
&((t_firsk_data *)obj->data)->character, pos, firsk_brain);
if (r.x || r.y)
g_env.moves++;
return (r);
}
static void firsk_draw(t_object *obj, t_point p)
{
return (character_draw(&((t_firsk_data *)obj->data)->character, p));
}
t_object firsk_init(t_memclass mc)
{
static const t_objecttype type
= {init: firsk_init, loop: firsk_loop, draw: firsk_draw,
walk_through: NULL};
static const t_character_sprites sprites = {
still: SPR_FIRSK,
walk_left: SPR_FIRSK_WALK_LEFT,
walk_right: SPR_FIRSK_WALK_RIGHT,
walk_up: SPR_FIRSK_WALK_UP,
walk_down: SPR_FIRSK_WALK_DOWN,
};
t_object r;
t_firsk_data *data;
r.type = type;
data = mem_alloc(error_err, mc, sizeof(t_firsk_data));
data->character = character_init((t_character_sprites *)&sprites, 5);
r.data = data;
return (r);
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/15 15:27:03 by mcolonna #+# #+# */
/* Updated: 2024/04/09 14:35:36 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 17:43:37 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -19,9 +19,9 @@ static t_point ketchup_loop(t_object *obj, t_point pos)
return (point_init(0, 0));
}
static void ketchup_draw(t_object *obj, int x, int y)
static void ketchup_draw(t_object *obj, t_point p)
{
sprite_draw(x, y, &((t_wall_data *)obj->data)->spr);
sprite_draw(p, &((t_wall_data *)obj->data)->spr);
}
static bool ketchup_walk_through(
@ -37,7 +37,11 @@ static bool ketchup_walk_through(
t_object ketchup_init(t_memclass mc)
{
static const t_objecttype type
= {init: ketchup_init, loop: ketchup_loop, draw: ketchup_draw,
= {
solid: false,
init: ketchup_init,
loop: ketchup_loop,
draw: ketchup_draw,
walk_through: ketchup_walk_through};
t_object r;
t_wall_data *data;

View file

@ -6,14 +6,15 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/15 15:27:03 by mcolonna #+# #+# */
/* Updated: 2024/04/09 15:28:02 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 18:10:32 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
static t_direction snas_brain(void)
static t_direction snas_brain(t_point pos)
{
(void)pos;
if (g_env.input[UP] && !g_env.input[DOWN])
return (UP);
if (g_env.input[DOWN] && !g_env.input[UP])
@ -35,15 +36,15 @@ static t_point snas_loop(t_object *obj, t_point pos)
return (r);
}
static void snas_draw(t_object *obj, int x, int y)
static void snas_draw(t_object *obj, t_point p)
{
return (character_draw(&((t_snas_data *)obj->data)->character, x, y));
return (character_draw(&((t_snas_data *)obj->data)->character, p));
}
t_object snas_init(t_memclass mc)
{
static const t_objecttype type
= {init: snas_init, loop: snas_loop, draw: snas_draw,
= {solid: false, init: snas_init, loop: snas_loop, draw: snas_draw,
walk_through: NULL};
static const t_character_sprites sprites = {
still: SPR_SNAS,
@ -57,7 +58,7 @@ t_object snas_init(t_memclass mc)
r.type = type;
data = mem_alloc(error_err, mc, sizeof(t_snas_data));
data->character = character_init((t_character_sprites *)&sprites);
data->character = character_init((t_character_sprites *)&sprites, 4);
r.data = data;
return (r);
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/15 15:27:03 by mcolonna #+# #+# */
/* Updated: 2024/04/09 15:27:39 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 17:44:49 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -19,15 +19,15 @@ static t_point wall_loop(t_object *obj, t_point pos)
return (point_init(0, 0));
}
static void wall_draw(t_object *obj, int x, int y)
static void wall_draw(t_object *obj, t_point p)
{
sprite_draw(x, y, &((t_wall_data *)obj->data)->spr);
sprite_draw(p, &((t_wall_data *)obj->data)->spr);
}
t_object wall_init(t_memclass mc)
{
static const t_objecttype type
= {init: wall_init, loop: wall_loop, draw: wall_draw,
= {solid: true, init: wall_init, loop: wall_loop, draw: wall_draw,
walk_through: NULL};
t_object r;
t_wall_data *data;

92
src/room/pathfinding.c Normal file
View file

@ -0,0 +1,92 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pathfinding.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/10 18:19:19 by mcolonna #+# #+# */
/* Updated: 2024/04/15 17:38:06 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
#include "pathfinding_utils.h"
static t_direction pathfinding_finishcase(
t_point start, t_point direction_p, t_path_map *map)
{
t_point after;
t_point before;
before = direction_p;
while (before.x != start.x || before.y != start.y)
{
after = before;
before = ((t_path_map_case *)*map_at(map, after))->before;
}
if (after.x - before.x == 1)
return (RIGHT);
if (after.x - before.x == -1)
return (LEFT);
if (after.y - before.y == 1)
return (DOWN);
return (UP);
}
static t_direction pathfinding_checkdirections(
t_tochecklist *tocheck, t_point case_checking,
t_path_map *map, t_pathfinding_env env)
{
t_direction d;
t_point direction_p;
t_path_map_case *direction_case;
d = -1;
while (++d < 4)
{
direction_p = case_checking;
point_addto(&direction_p, point_fromdirection(d));
direction_case = (t_path_map_case *)*map_at(map, direction_p);
if (!direction_case->to_check && !direction_case->solid)
{
direction_case->to_check = true;
direction_case->before = case_checking;
addtocheck(tocheck, direction_p);
}
if (direction_p.x == env.finish.x && direction_p.y == env.finish.y)
{
direction_case->before = case_checking;
return (pathfinding_finishcase(env.start, direction_p, map));
}
}
return (NO_DIRECTION);
}
t_direction pathfinding(t_point start, t_point finish)
{
const t_pathfinding_env env = {
start: start,
finish: finish,
mc: mem_subclass(error_err, g_env.mc)
};
t_path_map map;
t_point case_checking;
t_tochecklist tocheck;
t_direction r;
if (start.x == finish.x && start.y == finish.y)
return (NO_DIRECTION);
map = init_map(env.mc);
tocheck = inittochecklist(env.mc, map.dim, start);
case_checking = start;
while (case_checking.x != -1 || case_checking.y != -1)
{
r = pathfinding_checkdirections(&tocheck, case_checking, &map, env);
if (r != NO_DIRECTION)
return (r);
case_checking = nexttocheck(&tocheck);
}
mem_freeall(env.mc);
return (NO_DIRECTION);
}

View file

@ -0,0 +1,69 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pathfinding_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/15 17:35:13 by mcolonna #+# #+# */
/* Updated: 2024/04/15 17:37:46 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
#include "pathfinding_utils.h"
void path_map_case_init(t_point p, void **el, void *mc)
{
const t_room room = g_env.room;
const t_object *obj = room.objects[p.y * room.width + p.x];
const t_path_map_case r = {
to_check: false,
before: point_init(-1, -1),
solid: p.x == 0 || p.x == room.width - 1 || p.y == 0
|| p.y == room.height - 1 || (obj && obj->type.solid)
};
*el = mem_alloc(error_err, mc, sizeof(r));
**(t_path_map_case **)el = r;
}
t_path_map init_map(t_memclass mc)
{
t_path_map r;
r.dim.x = g_env.room.width;
r.dim.y = g_env.room.height;
r = map_init(mc, point_init(g_env.room.width, g_env.room.height));
map_foreach(&r, path_map_case_init, mc);
return (r);
}
t_tochecklist inittochecklist(t_memclass mc, t_point dim, t_point first)
{
t_tochecklist r;
int i;
r.cases = map_init(mc, dim);
i = -1;
while (++i < dim.x * dim.y)
{
r.cases.cases[i] = mem_alloc(error_err, mc, sizeof(t_point));
*((t_point *)r.cases.cases[i]) = point_init(-1, -1);
}
r.last = first;
r.current = first;
return (r);
}
void addtocheck(t_tochecklist *tocheck, t_point p)
{
*(t_point *)*map_at(&tocheck->cases, tocheck->last) = p;
tocheck->last = p;
}
t_point nexttocheck(t_tochecklist *tocheck)
{
tocheck->current = *(t_point *)*map_at(&tocheck->cases, tocheck->current);
return (tocheck->current);
}

View file

@ -0,0 +1,45 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* pathfinding_utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/10 18:21:55 by mcolonna #+# #+# */
/* Updated: 2024/04/15 17:37:42 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef PATHFINDING_UTILS_H
# define PATHFINDING_UTILS_H
typedef struct s_pathfinding_env
{
t_point start;
t_point finish;
t_memclass mc;
} t_pathfinding_env;
typedef struct s_tochecklist
{
t_map cases;
t_point last;
t_point current;
} t_tochecklist;
typedef struct s_path_map_case
{
bool solid;
bool to_check;
t_point before;
} t_path_map_case;
typedef t_map t_path_map;
void path_map_case_init(t_point p, void **el, void *mc);
t_path_map init_map(t_memclass mc);
t_tochecklist inittochecklist(t_memclass mc, t_point dim, t_point first);
void addtocheck(t_tochecklist *tocheck, t_point p);
t_point nexttocheck(t_tochecklist *tocheck);
#endif

View file

@ -6,18 +6,19 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/09 15:11:29 by mcolonna #+# #+# */
/* Updated: 2024/04/09 15:28:31 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 18:50:31 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
#include "room_utils.h"
static void room_fromfile3(t_room *room)
static t_room room_fromfile3(t_const_string path, t_room *room)
{
int x;
int y;
room_checkwallsallaround(path, room);
x = -1;
while (++x < room->width)
{
@ -26,7 +27,11 @@ static void room_fromfile3(t_room *room)
{
if (y == 0 || y == room->height - 1)
{
room->surfaces[y * room->width + x] = sprite_init(CASE_WALL);
room->surfaces[y * room->width + x]
= sprite_init(CASE_BORDER_BOTTOM);
if (y == 0)
room->surfaces[y * room->width + x]
= sprite_init(CASE_BORDER_TOP);
room->objects[y * room->width + x] = NULL;
}
else
@ -34,6 +39,7 @@ static void room_fromfile3(t_room *room)
CASE_FLOOR_1 + (x + y) % 2);
}
}
return (*room);
}
static bool room_fromfile2(
@ -66,73 +72,75 @@ static bool room_fromfile2(
return (true);
}
static t_room room_fromfile(t_const_string path)
static t_room room_fromfile(t_room *r, t_const_string path)
{
t_room r;
int fd;
const t_memclass mc = mem_subclass(error_err, g_env.mc);
int i;
room_getsize(mc, &r, path);
r.mc = mem_subclass(error_err, g_env.mc);
if (!str_eq(path + str_len(path) - 4, ".ber"))
error_str(path, "the room must be a '.ber' file.");
room_getsize(mc, r, path);
r->mc = mem_subclass(error_err, g_env.mc);
fd = open(path, O_RDONLY);
if (fd == -1)
error_perror(path);
r.surfaces = mem_alloc(error_err, r.mc, r.width * r.height
r->surfaces = mem_alloc(error_err, r->mc, r->width * r->height
* sizeof(t_sprite));
r.objects = mem_alloc(error_err, r.mc, r.width * r.height
r->objects = mem_alloc(error_err, r->mc, r->width * r->height
* sizeof(t_object *));
r.visuals = mem_alloc(error_err, r.mc, r.width * r.height
r->visuals = mem_alloc(error_err, r->mc, r->width * r->height
* sizeof(t_visual *));
i = -1;
while (++i < r.width * r.height)
r.visuals[i] = NULL;
while (++i < r->width * r->height)
r->visuals[i] = NULL;
i = 0;
while (room_fromfile2(fd, path, &i, &r))
while (room_fromfile2(fd, path, &i, r))
;
mem_freeall(mc);
room_fromfile3(&r);
return (r);
return (room_fromfile3(path, r));
}
void room_init(t_const_string path)
{
int i;
g_env.room = room_fromfile(path);
room_fromfile(&g_env.room, path);
g_env.moves = 0;
g_env.ketchup = 0;
g_env.max_ketchup = 0;
i = -1;
while (++i < g_env.room.width * g_env.room.height)
if (g_env.room.objects[i]
&& g_env.room.objects[i]->type.init == ketchup_init)
g_env.max_ketchup++;
g_env.max_ketchup = room_count(ketchup_init);
if (room_count(exit_init) != 1)
error_str(path, "there must be exactly 1 exit.");
if (room_count(ketchup_init) < 1)
error_str(path, "there must be at least 1 collectible.");
if (room_count(snas_init) != 1)
error_str(path, "there must be exactly 1 start position.");
room_checkaccessibilities(path);
}
void room_draw(t_room room)
{
int x;
int y;
t_point p;
t_object *obj;
y = -1;
while (++y < room.height)
camera_sync();
p.y = -1;
while (++p.y < room.height)
{
x = -1;
while (++x < room.width)
sprite_draw(x * 50, y * 50, room.surfaces + y * room.width + x);
p.x = -1;
while (++p.x < room.width)
sprite_draw(
to_camera_pos(p), room.surfaces + p.y * room.width + p.x);
}
y = -1;
while (++y < room.height)
p.y = -1;
while (++p.y < room.height)
{
x = -1;
while (++x < room.width)
p.x = -1;
while (++p.x < room.width)
{
obj = room.objects[y * room.width + x];
obj = room.objects[p.y * room.width + p.x];
if (obj)
obj->type.draw(obj, x * 50, y * 50);
visual_loop(&room.visuals[y * room.width + x], x * 50, y * 50);
obj->type.draw(obj, to_camera_pos(p));
visual_loop(
&room.visuals[p.y * room.width + p.x], to_camera_pos(p));
}
}
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/09 15:18:38 by mcolonna #+# #+# */
/* Updated: 2024/04/09 15:25:41 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 18:10:15 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -39,3 +39,22 @@ bool room_canwalk(t_room room, t_character *character, t_point pos)
mem_free(obj);
return (r);
}
t_point room_find(t_object_init objtype)
{
t_point p;
t_object *obj;
p.x = -1;
while (++p.x < g_env.room.width)
{
p.y = -1;
while (++p.y < g_env.room.height)
{
obj = g_env.room.objects[p.y * g_env.room.width + p.x];
if (obj && obj->type.init == objtype)
return (p);
}
}
return (point_init(-1, -1));
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/09 15:23:43 by mcolonna #+# #+# */
/* Updated: 2024/04/09 15:24:07 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 18:49:56 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -21,5 +21,9 @@ typedef struct s_roomcase
void room_getsize(t_memclass mc, t_room *r, t_const_string path);
t_roomcase *getroomcase(t_const_string path, char c);
int room_count(t_object_init objtype);
void room_checkwallsallaround(t_const_string path, t_room *room);
t_point to_camera_pos(t_point p);
void room_checkaccessibilities(t_const_string path);
#endif

View file

@ -1,12 +1,12 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* room_utils.c :+: :+: :+: */
/* room_utils1.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/09 15:21:33 by mcolonna #+# #+# */
/* Updated: 2024/04/09 15:24:42 by mcolonna ### ########.fr */
/* Updated: 2024/04/15 18:59:54 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -19,6 +19,7 @@ static t_roomcase g_roomcases[] = {
{c: 'P', object: snas_init},
{c: 'C', object: ketchup_init},
{c: 'E', object: exit_init},
{c: 'F', object: firsk_init},
{c: '\0'}
};
@ -55,7 +56,7 @@ void room_getsize(t_memclass mc, t_room *r, t_const_string path)
if (!line)
break ;
if (getlinelen(line) != r->width)
error_str(path, "the lines have different lengths");
error_str(path, "the room must be rectangular");
r->height++;
}
}
@ -73,3 +74,40 @@ t_roomcase *getroomcase(t_const_string path, char c)
error_str(path, "unknown char");
return (NULL);
}
int room_count(t_object_init objtype)
{
int i;
int r;
r = 0;
i = -1;
while (++i < g_env.room.width * g_env.room.height)
if (g_env.room.objects[i]
&& g_env.room.objects[i]->type.init == objtype)
r++;
return (r);
}
void room_checkaccessibilities(t_const_string path)
{
t_point p;
t_object *obj;
t_point snas_pos;
snas_pos = room_find(snas_init);
p.y = -1;
while (++p.y < g_env.room.height)
{
p.x = -1;
while (++p.x < g_env.room.width)
{
obj = g_env.room.objects[p.y * g_env.room.width + p.x];
if (obj && obj->type.init == ketchup_init)
if (pathfinding(snas_pos, p) == NO_DIRECTION)
error_str(path, "all collectibles must be accessible.");
}
}
if (pathfinding(snas_pos, room_find(exit_init)) == NO_DIRECTION)
error_str(path, "the exit must be accessible.");
}

53
src/room/room_utils2.c Normal file
View file

@ -0,0 +1,53 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* room_utils2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/09 16:04:41 by mcolonna #+# #+# */
/* Updated: 2024/04/11 17:24:53 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
#include "room_utils.h"
static void checkwall(t_const_string path, t_object *obj)
{
if (!obj || obj->type.init != wall_init)
error_str(path, "there must have walls all around the room");
}
void room_checkwallsallaround(t_const_string path, t_room *room)
{
int i;
i = -1;
while (++i < room->width)
checkwall(path, room->objects[i]);
i = (room->height - 1) * room->width - 1;
while (++i < room->width * room->height)
checkwall(path, room->objects[i]);
i = 0;
while (i < room->width * room->height)
{
checkwall(path, room->objects[i]);
i += room->width;
}
i = room->width - 1;
while (i < room->width * room->height)
{
checkwall(path, room->objects[i]);
i += room->width;
}
}
t_point to_camera_pos(t_point p)
{
t_point r;
r.x = p.x * 50 - g_env.camera.pos.x;
r.y = p.y * 50 - g_env.camera.pos.y;
return (r);
}

View file

@ -6,17 +6,17 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/03 15:35:28 by mcolonna #+# #+# */
/* Updated: 2024/04/03 16:01:04 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 17:08:14 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
void visual_loop(t_visual **visual, int x, int y)
void visual_loop(t_visual **visual, t_point p)
{
if (!(*visual))
return ;
if (!sprite_draw(x, y, &(*visual)->spr))
if (!sprite_draw(p, &(*visual)->spr))
{
mem_free(*visual);
*visual = 0;

49
src/utils/map.c Normal file
View file

@ -0,0 +1,49 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* map.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/12 19:14:26 by mcolonna #+# #+# */
/* Updated: 2024/04/15 15:01:01 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
static void set_null(t_point p, void **el, void *arg)
{
(void)p;
(void)arg;
*el = NULL;
}
t_map map_init(t_memclass mc, t_point dim)
{
t_map r;
r.dim = dim;
r.cases = mem_alloc(error_err, mc, dim.x * dim.y * sizeof(void *));
map_foreach(&r, set_null, NULL);
return (r);
}
void **map_at(t_map *map, t_point p)
{
return (&map->cases[p.y * map->dim.x + p.x]);
}
void map_foreach(t_map *map, void (*f)(t_point p, void **el, void *arg),
void *arg)
{
t_point p;
p.y = -1;
while (++p.y < map->dim.y)
{
p.x = -1;
while (++p.x < map->dim.x)
f(p, map_at(map, p), arg);
}
}

View file

@ -6,7 +6,7 @@
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/15 15:24:37 by mcolonna #+# #+# */
/* Updated: 2024/04/02 14:41:19 by mcolonna ### ########.fr */
/* Updated: 2024/04/11 17:25:55 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
@ -19,6 +19,13 @@ t_point point_init(int x, int y)
return (r);
}
t_point point_add(t_point point, int x)
{
point.x += x;
point.y += x;
return (point);
}
void point_addto(t_point *dest, t_point src)
{
dest->x += src.x;

20
src/utils/point2.c Normal file
View file

@ -0,0 +1,20 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* point2.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mcolonna <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/04/11 17:53:07 by mcolonna #+# #+# */
/* Updated: 2024/04/11 18:06:44 by mcolonna ### ########.fr */
/* */
/* ************************************************************************** */
#include "includes.h"
t_point point_subpoint(t_point p1, t_point p2)
{
p1.x -= p2.x;
p1.y -= p2.y;
return (p1);
}