s
This commit is contained in:
parent
8c0d63300d
commit
fc2b243daa
6 changed files with 259 additions and 207 deletions
4
Makefile
4
Makefile
|
@ -6,13 +6,13 @@
|
|||
# By: greg <greg@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/07/29 13:08:42 by greg #+# #+# #
|
||||
# Updated: 2024/10/09 03:07:50 by greg ### ########.fr #
|
||||
# Updated: 2024/10/15 12:53:36 by marvin ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
NAME = cub3d
|
||||
|
||||
SRC = algo.c
|
||||
SRC = $(wildcard *.c)
|
||||
|
||||
OBJS = ${SRC:.c=.o}
|
||||
|
||||
|
|
209
algo.c
209
algo.c
|
@ -3,10 +3,10 @@
|
|||
/* ::: :::::::: */
|
||||
/* algo.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mc <mc@student.42.fr> +#+ +:+ +#+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/10/01 16:24:58 by grobledo #+# #+# */
|
||||
/* Updated: 2024/10/14 18:35:03 by mc ### ########.fr */
|
||||
/* Updated: 2024/10/15 12:54:19 by mcolonna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
@ -16,10 +16,9 @@
|
|||
#include <X11/X.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static void *g_mlx = NULL;
|
||||
static void *g_win = NULL;
|
||||
|
||||
static t_ray g_ray;
|
||||
void *g_mlx = NULL;
|
||||
void *g_win = NULL;
|
||||
t_ray g_ray;
|
||||
|
||||
// int worldMap[mapWidth][mapHeight]=
|
||||
// {
|
||||
|
@ -77,13 +76,6 @@ int worldMap[mapWidth][mapHeight]=
|
|||
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
|
||||
};
|
||||
|
||||
static void vector_from_rotation(
|
||||
double *vecX, double *vecY, double angle, double norm)
|
||||
{
|
||||
*vecX = -cos(angle) * norm;
|
||||
*vecY = sin(angle) * norm;
|
||||
}
|
||||
|
||||
static int initalgo()
|
||||
{
|
||||
// TODO from map
|
||||
|
@ -93,136 +85,7 @@ static int initalgo()
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int render(u_int32_t *img_data)
|
||||
{
|
||||
int x; // px
|
||||
|
||||
// clear image data
|
||||
ft_bzero(img_data, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(int)); // TODO why
|
||||
|
||||
// 1
|
||||
double dirX, dirY, planeX, planeY;
|
||||
vector_from_rotation(&dirX, &dirY, g_ray.rot, 1);
|
||||
vector_from_rotation(&planeX, &planeY, g_ray.rot + PI/2, FOV);
|
||||
|
||||
x = 0;
|
||||
while (x < SCREEN_WIDTH)
|
||||
{
|
||||
// case player on map (cases)
|
||||
int mapX = (int)g_ray.posX;
|
||||
// case player on map (cases)
|
||||
int mapY = (int)g_ray.posY;
|
||||
|
||||
// vector ray direction (1)
|
||||
double raydirX, raydirY;
|
||||
{
|
||||
// ray direction in [-1;+1]. the highter the more to the right (1)
|
||||
double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1;
|
||||
raydirX = dirX + planeX * ray_direction;
|
||||
raydirY = dirY + planeY * ray_direction;
|
||||
}
|
||||
|
||||
// longueur du rayon dans une même colonne de cases (cases)
|
||||
double deltadistX = (raydirX == 0) ? 1e30 : fabs(1 / raydirX);
|
||||
// longueur du rayon dans une même ligne de cases (cases)
|
||||
double deltadistY = (raydirY == 0) ? 1e30 : fabs(1 / raydirY);
|
||||
|
||||
// longueur du rayon entre pos actuelle et pos du prochain coté ouest ou est d'une box
|
||||
double sidedistX;
|
||||
// longueur du rayon entre pos actuelle et pos du prochain coté nord ou sub d'une box
|
||||
double sidedistY;
|
||||
|
||||
// direction du rayon sur x (+1 or -1)
|
||||
int stepX;
|
||||
// direction du rayon sur y (+1 or -1)
|
||||
int stepY;
|
||||
|
||||
if (raydirX < 0)
|
||||
{
|
||||
stepX = -1;
|
||||
sidedistX = (g_ray.posX - mapX) * deltadistX;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepX = 1;
|
||||
sidedistX = (mapX + 1.0 - g_ray.posX) * deltadistX;
|
||||
}
|
||||
if (raydirY < 0)
|
||||
{
|
||||
stepY = -1;
|
||||
sidedistY = (g_ray.posY - mapY) * deltadistY;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepY = 1;
|
||||
sidedistY = (mapY + 1.0 - g_ray.posY) * deltadistY;
|
||||
}
|
||||
|
||||
bool hit = false;
|
||||
bool side;
|
||||
while(!hit)
|
||||
{
|
||||
// jump to next map square, either in x-direction, or in y-direction
|
||||
if(sidedistX < sidedistY)
|
||||
{
|
||||
sidedistX += deltadistX;
|
||||
mapX += stepX;
|
||||
side = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidedistY += deltadistY;
|
||||
mapY += stepY;
|
||||
side = true;
|
||||
}
|
||||
// check if ray has hit a wall
|
||||
if(worldMap[mapX][mapY] == 1)
|
||||
hit = true;
|
||||
}
|
||||
|
||||
// calcul lenght of ray (shortest perpendicular distance between wall and camera plane) (1)
|
||||
double perpwalldist;
|
||||
if(!side)
|
||||
perpwalldist = (sidedistX - deltadistX);
|
||||
else
|
||||
perpwalldist = (sidedistY - deltadistY);
|
||||
|
||||
// calculate height of line to draw on screen (px)
|
||||
int lineHeight = (int)(SCREEN_HEIGHT / perpwalldist);
|
||||
|
||||
// calculate lowest and highest pixel to fill in current stripe
|
||||
int drawStart = -lineHeight / 2 + SCREEN_HEIGHT / 2;
|
||||
if(drawStart < 0)
|
||||
drawStart = 0;
|
||||
int drawEnd = lineHeight / 2 + SCREEN_HEIGHT / 2;
|
||||
if(drawEnd >= SCREEN_HEIGHT)
|
||||
drawEnd = SCREEN_HEIGHT - 1;
|
||||
|
||||
// draw vertical line
|
||||
int y = 0;
|
||||
while (y < drawStart)
|
||||
{
|
||||
img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING;
|
||||
y++;
|
||||
}
|
||||
while (y < drawEnd)
|
||||
{
|
||||
img_data[y * SCREEN_WIDTH + x] = COLOR_WALL;
|
||||
y++;
|
||||
}
|
||||
while (y < SCREEN_HEIGHT)
|
||||
{
|
||||
img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR;
|
||||
y++;
|
||||
}
|
||||
|
||||
x++;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void draw_screen() {
|
||||
void draw_screen(void) {
|
||||
int bpp;
|
||||
int size_line;
|
||||
int endian;
|
||||
|
@ -239,66 +102,6 @@ static void draw_screen() {
|
|||
mlx_put_image_to_window(g_mlx, g_win, img_ptr, 0, 0);
|
||||
}
|
||||
|
||||
static int keypress(int keycode)
|
||||
{
|
||||
double dirX, dirY, planeX, planeY;
|
||||
vector_from_rotation(&dirX, &dirY, g_ray.rot, 1);
|
||||
vector_from_rotation(&planeX, &planeY, g_ray.rot + PI/2, FOV);
|
||||
|
||||
//move forward if no wall in front of you
|
||||
if (keycode == XK_Up || keycode == XK_z || keycode == XK_w)
|
||||
{
|
||||
if (worldMap[(int)((g_ray.posX + dirX * MOVE_SPEED))][(int)(g_ray.posY)] != 1)
|
||||
g_ray.posX += dirX * MOVE_SPEED;
|
||||
if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY + dirY * MOVE_SPEED)] != 1)
|
||||
g_ray.posY += dirY * MOVE_SPEED;
|
||||
}
|
||||
//move backwards if no wall behind you
|
||||
if (keycode == XK_Down || keycode == XK_s)
|
||||
{
|
||||
if (worldMap[(int)(g_ray.posX - dirX * MOVE_SPEED)][(int)(g_ray.posY)] != 1)
|
||||
g_ray.posX -= dirX * MOVE_SPEED;
|
||||
if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY - dirY * MOVE_SPEED)] != 1)
|
||||
g_ray.posY -= dirY * MOVE_SPEED;
|
||||
}
|
||||
//rotate to the right
|
||||
if (keycode == XK_Right || keycode == XK_d)
|
||||
{
|
||||
g_ray.rot += ROT_SPEED;
|
||||
// double oldDirX;
|
||||
// double oldPlaneX;
|
||||
// //both camera direction and camera plane must be rotated
|
||||
// oldDirX = dirX;
|
||||
// dirX = dirX * cos(-ROT_SPEED) - dirY * sin(-ROT_SPEED);
|
||||
// dirY = oldDirX * sin(-ROT_SPEED) + dirY * cos(-ROT_SPEED);
|
||||
// oldPlaneX = planeX;
|
||||
// planeX = planeX * cos(-ROT_SPEED) - planeY * sin(-ROT_SPEED);
|
||||
// planeY = oldPlaneX * sin(-ROT_SPEED) + planeY * cos(-ROT_SPEED);
|
||||
}
|
||||
//rotate to the left
|
||||
if (keycode == XK_Left || keycode == XK_q || keycode == XK_a)
|
||||
{
|
||||
g_ray.rot -= ROT_SPEED;
|
||||
// double oldDirX;
|
||||
// double oldPlaneX;
|
||||
// //both camera direction and camera plane must be rotated
|
||||
// oldDirX = dirX;
|
||||
// dirX = dirX * cos(ROT_SPEED) - dirY * sin(ROT_SPEED);
|
||||
// dirY = oldDirX * sin(ROT_SPEED) + dirY * cos(ROT_SPEED);
|
||||
// oldPlaneX = planeX;
|
||||
// planeX = planeX * cos(ROT_SPEED) - planeY * sin(ROT_SPEED);
|
||||
// planeY = oldPlaneX * sin(ROT_SPEED) + planeY * cos(ROT_SPEED);
|
||||
}
|
||||
|
||||
if (keycode == XK_Escape)
|
||||
exit(0);
|
||||
|
||||
printf("x:%f y:%f\n", g_ray.posX, g_ray.posY);
|
||||
// render the updated frame after key press
|
||||
draw_screen();
|
||||
return (0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// Initialisation
|
||||
|
|
19
algo.h
19
algo.h
|
@ -3,10 +3,10 @@
|
|||
/* ::: :::::::: */
|
||||
/* algo.h :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mc <mc@student.42.fr> +#+ +:+ +#+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/09/30 15:45:59 by grobledo #+# #+# */
|
||||
/* Updated: 2024/10/14 18:26:05 by mc ### ########.fr */
|
||||
/* Updated: 2024/10/15 12:54:12 by mcolonna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "Minilibx/mlx.h"
|
||||
#include "Minilibx/mlx_int.h"
|
||||
# include "Libft/libft.h"
|
||||
|
@ -40,4 +41,18 @@ typedef struct s_ray
|
|||
double rot;
|
||||
} t_ray;
|
||||
|
||||
extern void *g_mlx;
|
||||
extern void *g_win;
|
||||
extern t_ray g_ray;
|
||||
extern int worldMap[mapWidth][mapHeight];
|
||||
|
||||
void vector_from_rotation(
|
||||
double *vecX, double *vecY, double angle, double norm);
|
||||
|
||||
int keypress(int keycode);
|
||||
|
||||
int render(u_int32_t *img_data);
|
||||
|
||||
void draw_screen(void);
|
||||
|
||||
#endif
|
||||
|
|
73
move.c
Normal file
73
move.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* move.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/10/15 12:47:34 by mcolonna #+# #+# */
|
||||
/* Updated: 2024/10/15 12:52:05 by mcolonna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "algo.h"
|
||||
|
||||
int keypress(int keycode)
|
||||
{
|
||||
double dirX, dirY, planeX, planeY;
|
||||
vector_from_rotation(&dirX, &dirY, g_ray.rot, 1);
|
||||
vector_from_rotation(&planeX, &planeY, g_ray.rot + PI/2, FOV);
|
||||
|
||||
//move forward if no wall in front of you
|
||||
if (keycode == XK_Up || keycode == XK_z || keycode == XK_w)
|
||||
{
|
||||
if (worldMap[(int)((g_ray.posX + dirX * MOVE_SPEED))][(int)(g_ray.posY)] != 1)
|
||||
g_ray.posX += dirX * MOVE_SPEED;
|
||||
if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY + dirY * MOVE_SPEED)] != 1)
|
||||
g_ray.posY += dirY * MOVE_SPEED;
|
||||
}
|
||||
//move backwards if no wall behind you
|
||||
if (keycode == XK_Down || keycode == XK_s)
|
||||
{
|
||||
if (worldMap[(int)(g_ray.posX - dirX * MOVE_SPEED)][(int)(g_ray.posY)] != 1)
|
||||
g_ray.posX -= dirX * MOVE_SPEED;
|
||||
if (worldMap[(int)(g_ray.posX)][(int)(g_ray.posY - dirY * MOVE_SPEED)] != 1)
|
||||
g_ray.posY -= dirY * MOVE_SPEED;
|
||||
}
|
||||
//rotate to the right
|
||||
if (keycode == XK_Right || keycode == XK_d)
|
||||
{
|
||||
g_ray.rot += ROT_SPEED;
|
||||
// double oldDirX;
|
||||
// double oldPlaneX;
|
||||
// //both camera direction and camera plane must be rotated
|
||||
// oldDirX = dirX;
|
||||
// dirX = dirX * cos(-ROT_SPEED) - dirY * sin(-ROT_SPEED);
|
||||
// dirY = oldDirX * sin(-ROT_SPEED) + dirY * cos(-ROT_SPEED);
|
||||
// oldPlaneX = planeX;
|
||||
// planeX = planeX * cos(-ROT_SPEED) - planeY * sin(-ROT_SPEED);
|
||||
// planeY = oldPlaneX * sin(-ROT_SPEED) + planeY * cos(-ROT_SPEED);
|
||||
}
|
||||
//rotate to the left
|
||||
if (keycode == XK_Left || keycode == XK_q || keycode == XK_a)
|
||||
{
|
||||
g_ray.rot -= ROT_SPEED;
|
||||
// double oldDirX;
|
||||
// double oldPlaneX;
|
||||
// //both camera direction and camera plane must be rotated
|
||||
// oldDirX = dirX;
|
||||
// dirX = dirX * cos(ROT_SPEED) - dirY * sin(ROT_SPEED);
|
||||
// dirY = oldDirX * sin(ROT_SPEED) + dirY * cos(ROT_SPEED);
|
||||
// oldPlaneX = planeX;
|
||||
// planeX = planeX * cos(ROT_SPEED) - planeY * sin(ROT_SPEED);
|
||||
// planeY = oldPlaneX * sin(ROT_SPEED) + planeY * cos(ROT_SPEED);
|
||||
}
|
||||
|
||||
if (keycode == XK_Escape)
|
||||
exit(0);
|
||||
|
||||
printf("x:%f y:%f\n", g_ray.posX, g_ray.posY);
|
||||
// render the updated frame after key press
|
||||
draw_screen();
|
||||
return (0);
|
||||
}
|
142
render.c
Normal file
142
render.c
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* render.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/10/15 12:40:52 by mcolonna #+# #+# */
|
||||
/* Updated: 2024/10/15 12:51:25 by mcolonna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "algo.h"
|
||||
|
||||
int render(u_int32_t *img_data)
|
||||
{
|
||||
int x; // px
|
||||
|
||||
// clear image data
|
||||
ft_bzero(img_data, SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(int)); // TODO why
|
||||
|
||||
// 1
|
||||
double dirX, dirY, planeX, planeY;
|
||||
vector_from_rotation(&dirX, &dirY, g_ray.rot, 1);
|
||||
vector_from_rotation(&planeX, &planeY, g_ray.rot + PI/2, FOV);
|
||||
|
||||
x = 0;
|
||||
while (x < SCREEN_WIDTH)
|
||||
{
|
||||
// case player on map (cases)
|
||||
int mapX = (int)g_ray.posX;
|
||||
// case player on map (cases)
|
||||
int mapY = (int)g_ray.posY;
|
||||
|
||||
// vector ray direction (1)
|
||||
double raydirX, raydirY;
|
||||
{
|
||||
// ray direction in [-1;+1]. the highter the more to the right (1)
|
||||
double ray_direction = 2 * x / (double)SCREEN_WIDTH - 1;
|
||||
raydirX = dirX + planeX * ray_direction;
|
||||
raydirY = dirY + planeY * ray_direction;
|
||||
}
|
||||
|
||||
// longueur du rayon dans une même colonne de cases (cases)
|
||||
double deltadistX = (raydirX == 0) ? 1e30 : fabs(1 / raydirX);
|
||||
// longueur du rayon dans une même ligne de cases (cases)
|
||||
double deltadistY = (raydirY == 0) ? 1e30 : fabs(1 / raydirY);
|
||||
|
||||
// longueur du rayon entre pos actuelle et pos du prochain coté ouest ou est d'une box
|
||||
double sidedistX;
|
||||
// longueur du rayon entre pos actuelle et pos du prochain coté nord ou sub d'une box
|
||||
double sidedistY;
|
||||
|
||||
// direction du rayon sur x (+1 or -1)
|
||||
int stepX;
|
||||
// direction du rayon sur y (+1 or -1)
|
||||
int stepY;
|
||||
|
||||
if (raydirX < 0)
|
||||
{
|
||||
stepX = -1;
|
||||
sidedistX = (g_ray.posX - mapX) * deltadistX;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepX = 1;
|
||||
sidedistX = (mapX + 1.0 - g_ray.posX) * deltadistX;
|
||||
}
|
||||
if (raydirY < 0)
|
||||
{
|
||||
stepY = -1;
|
||||
sidedistY = (g_ray.posY - mapY) * deltadistY;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepY = 1;
|
||||
sidedistY = (mapY + 1.0 - g_ray.posY) * deltadistY;
|
||||
}
|
||||
|
||||
bool hit = false;
|
||||
bool side;
|
||||
while(!hit)
|
||||
{
|
||||
// jump to next map square, either in x-direction, or in y-direction
|
||||
if(sidedistX < sidedistY)
|
||||
{
|
||||
sidedistX += deltadistX;
|
||||
mapX += stepX;
|
||||
side = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidedistY += deltadistY;
|
||||
mapY += stepY;
|
||||
side = true;
|
||||
}
|
||||
// check if ray has hit a wall
|
||||
if(worldMap[mapX][mapY] == 1)
|
||||
hit = true;
|
||||
}
|
||||
|
||||
// calcul lenght of ray (shortest perpendicular distance between wall and camera plane) (1)
|
||||
double perpwalldist;
|
||||
if(!side)
|
||||
perpwalldist = (sidedistX - deltadistX);
|
||||
else
|
||||
perpwalldist = (sidedistY - deltadistY);
|
||||
|
||||
// calculate height of line to draw on screen (px)
|
||||
int lineHeight = (int)(SCREEN_HEIGHT / perpwalldist);
|
||||
|
||||
// calculate lowest and highest pixel to fill in current stripe
|
||||
int drawStart = -lineHeight / 2 + SCREEN_HEIGHT / 2;
|
||||
if(drawStart < 0)
|
||||
drawStart = 0;
|
||||
int drawEnd = lineHeight / 2 + SCREEN_HEIGHT / 2;
|
||||
if(drawEnd >= SCREEN_HEIGHT)
|
||||
drawEnd = SCREEN_HEIGHT - 1;
|
||||
|
||||
// draw vertical line
|
||||
int y = 0;
|
||||
while (y < drawStart)
|
||||
{
|
||||
img_data[y * SCREEN_WIDTH + x] = COLOR_CEILING;
|
||||
y++;
|
||||
}
|
||||
while (y < drawEnd)
|
||||
{
|
||||
img_data[y * SCREEN_WIDTH + x] = COLOR_WALL;
|
||||
y++;
|
||||
}
|
||||
while (y < SCREEN_HEIGHT)
|
||||
{
|
||||
img_data[y * SCREEN_WIDTH + x] = COLOR_FLOOR;
|
||||
y++;
|
||||
}
|
||||
|
||||
x++;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
19
utils.c
Normal file
19
utils.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* utils.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mcolonna <mcolonna@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/10/15 12:38:40 by mcolonna #+# #+# */
|
||||
/* Updated: 2024/10/15 12:39:15 by mcolonna ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "algo.h"
|
||||
|
||||
void vector_from_rotation(double *vecX, double *vecY, double angle, double norm)
|
||||
{
|
||||
*vecX = -cos(angle) * norm;
|
||||
*vecY = sin(angle) * norm;
|
||||
}
|
Loading…
Add table
Reference in a new issue