feat(game): 添加基础游戏引擎和渲染模块
- 新增游戏引擎核心模块,包括初始化和运行逻辑 - 实现基本的渲染功能,支持控制台输出 - 添加物理引擎基础,包括碰撞检测 - 集成日志系统,用于调试和信息输出 - 创建窗口和输入管理模块
This commit is contained in:
236
game_engine/utils/ge_kfifo.h
Normal file
236
game_engine/utils/ge_kfifo.h
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* A generic kernel FIFO implementation
|
||||
*
|
||||
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef __GE_KFIFO_H__
|
||||
#define __GE_KFIFO_H__
|
||||
/**
|
||||
* 仿照linux内核中的kfifo实现
|
||||
*/
|
||||
|
||||
#ifndef GE_MEMORY_BARRIR
|
||||
#define GE_MEMORY_BARRIR() __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#ifndef GE_ARRAY_SIZE
|
||||
#define GE_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif
|
||||
|
||||
struct __ge_kfifo {
|
||||
unsigned int in;
|
||||
unsigned int out;
|
||||
unsigned int mask;
|
||||
unsigned int esize;
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define __STRUCT_GE_KFIFO(type, size) \
|
||||
{ \
|
||||
struct __ge_kfifo kfifo; \
|
||||
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
|
||||
}
|
||||
|
||||
/**
|
||||
* DECLARE_KFIFO - macro to declare a fifo object
|
||||
* @fifo: name of the declared fifo
|
||||
* @type: type of the fifo elements
|
||||
* @size: the number of elements in the fifo, this must be a power of 2
|
||||
*/
|
||||
#define DECLARE_GE_KFIFO(fifo, type, size, tname) struct tname __STRUCT_GE_KFIFO(type, size) fifo
|
||||
|
||||
#define INIT_GE_KFIFO(fifo, type) do { \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__kfifo->in = 0; \
|
||||
__kfifo->out = 0; \
|
||||
__kfifo->mask = GE_ARRAY_SIZE((fifo).buf) - 1; \
|
||||
__kfifo->esize = sizeof(*(fifo).buf); \
|
||||
__kfifo->data = (fifo).buf; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* DEFINE_KFIFO - macro to define and initialize a fifo
|
||||
* @fifo: name of the declared fifo datatype
|
||||
* @type: type of the fifo elements
|
||||
* @size: the number of elements in the fifo, this must be a power of 2
|
||||
*
|
||||
* Note: the macro can be used for global and local fifo data type variables.
|
||||
*/
|
||||
#define DEFINE_GE_KFIFO(fifo, type, size, tname) \
|
||||
DECLARE_GE_KFIFO(fifo, type, size, tname) = \
|
||||
(struct tname) { { \
|
||||
.in = 0, \
|
||||
.out = 0, \
|
||||
.mask = GE_ARRAY_SIZE((fifo).buf) - 1, \
|
||||
.esize = sizeof(*(fifo).buf), \
|
||||
.data = (fifo).buf, \
|
||||
}, { 0 } }
|
||||
|
||||
/**
|
||||
* kfifo_size - returns the size of the fifo in elements
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_size(fifo) \
|
||||
((fifo)->kfifo.mask + 1)
|
||||
|
||||
/**
|
||||
* kfifo_len - returns the number of used elements in the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_len(fifo) \
|
||||
((fifo)->kfifo.in - (fifo)->kfifo.out)
|
||||
|
||||
/**
|
||||
* kfifo_is_empty - returns true if the fifo is empty
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_is_empty(fifo) \
|
||||
((fifo)->kfifo.in == (fifo)->kfifo.out)
|
||||
|
||||
/**
|
||||
* kfifo_is_full - returns true if the fifo is full
|
||||
* @fifo: address of the fifo to be used
|
||||
*/
|
||||
#define ge_kfifo_is_full(fifo) (ge_kfifo_len(fifo) > (fifo)->kfifo.mask)
|
||||
|
||||
/**
|
||||
* kfifo_put - put data into the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @val: the data to be added
|
||||
*
|
||||
* This macro copies the given value into the fifo.
|
||||
* It returns 0 if the fifo was full. Otherwise it returns the number
|
||||
* processed elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
#define ge_kfifo_put(fifo, val) do { \
|
||||
unsigned int __ret; \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__ret = !ge_kfifo_is_full(fifo); \
|
||||
if (__ret) { \
|
||||
((fifo)->buf)[__kfifo->in & __kfifo->mask] = val; \
|
||||
/*smp_wmb();*/ \
|
||||
GE_MEMORY_BARRIR(); \
|
||||
__kfifo->in++; \
|
||||
} \
|
||||
/*__ret;*/ \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* kfifo_get - get data from the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @val: address where to store the data
|
||||
*
|
||||
* This macro reads the data from the fifo.
|
||||
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
||||
* processed elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
#define ge_kfifo_get(fifo, val) do { \
|
||||
unsigned int __ret; \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__ret = !ge_kfifo_is_empty(fifo); \
|
||||
if (__ret) { \
|
||||
*val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \
|
||||
/*smp_wmb();*/ \
|
||||
GE_MEMORY_BARRIR(); \
|
||||
__kfifo->out++; \
|
||||
} \
|
||||
/*__ret;*/ \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* kfifo_peek - get data from the fifo without removing
|
||||
* @fifo: address of the fifo to be used
|
||||
* @val: address where to store the data
|
||||
*
|
||||
* This reads the data from the fifo without removing it from the fifo.
|
||||
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
||||
* processed elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
#define ge_kfifo_peek(fifo, val) do { \
|
||||
unsigned int __ret; \
|
||||
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
||||
__ret = !kfifo_is_empty(fifo); \
|
||||
if (__ret) { \
|
||||
*val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \
|
||||
/*smp_wmb();*/ \
|
||||
GE_MEMORY_BARRIR(); \
|
||||
} \
|
||||
/*__ret;*/ \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* kfifo_in - put data into the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @buf: the data to be added
|
||||
* @n: number of elements to be added
|
||||
*
|
||||
* This macro copies the given buffer into the fifo and returns the
|
||||
* number of copied elements.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
/*
|
||||
#define kfifo_in(fifo, buf, n) \
|
||||
({ \
|
||||
typeof((fifo) + 1) __tmp = (fifo); \
|
||||
typeof(__tmp->ptr_const) __buf = (buf); \
|
||||
unsigned long __n = (n); \
|
||||
const size_t __recsize = sizeof(*__tmp->rectype); \
|
||||
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||
(__recsize) ?\
|
||||
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
|
||||
__kfifo_in(__kfifo, __buf, __n); \
|
||||
})
|
||||
*/
|
||||
/**
|
||||
* kfifo_out - get data from the fifo
|
||||
* @fifo: address of the fifo to be used
|
||||
* @buf: pointer to the storage buffer
|
||||
* @n: max. number of elements to get
|
||||
*
|
||||
* This macro gets some data from the fifo and returns the numbers of elements
|
||||
* copied.
|
||||
*
|
||||
* Note that with only one concurrent reader and one concurrent
|
||||
* writer, you don't need extra locking to use these macro.
|
||||
*/
|
||||
/*
|
||||
#define kfifo_out(fifo, buf, n) \
|
||||
({ \
|
||||
typeof((fifo) + 1) __tmp = (fifo); \
|
||||
typeof(__tmp->ptr) __buf = (buf); \
|
||||
unsigned long __n = (n); \
|
||||
const size_t __recsize = sizeof(*__tmp->rectype); \
|
||||
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
||||
(__recsize) ?\
|
||||
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
|
||||
__kfifo_out(__kfifo, __buf, __n); \
|
||||
})
|
||||
*/
|
||||
|
||||
#endif // __GE_KFIFO_H__
|
||||
129
game_engine/utils/ge_maroc.h
Normal file
129
game_engine/utils/ge_maroc.h
Normal file
@@ -0,0 +1,129 @@
|
||||
#ifndef __GE_MAROC_H__
|
||||
#define __GE_MAROC_H__
|
||||
|
||||
#define GE_ABS(x) ((x) > 0 : (x) : -(x))
|
||||
#define GE_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define GE_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define _GE_STR(x) #x
|
||||
#define GE_STRINGIFY(x) _GE_STR(x)
|
||||
|
||||
#define GE_SAFE_CALL(func, ...) \
|
||||
do { \
|
||||
if (func) func(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#endif // __GE_MAROC_H__
|
||||
|
||||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
/*
|
||||
#ifndef __MACRO_H__
|
||||
#define __MACRO_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// macro stringizing
|
||||
#define str_temp(x) #x
|
||||
#define str(x) str_temp(x)
|
||||
|
||||
// strlen() for string constant
|
||||
#define STRLEN(CONST_STR) (sizeof(CONST_STR) - 1)
|
||||
|
||||
// calculate the length of an array
|
||||
#define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
// macro concatenation
|
||||
#define concat_temp(x, y) x ## y
|
||||
#define concat(x, y) concat_temp(x, y)
|
||||
#define concat3(x, y, z) concat(concat(x, y), z)
|
||||
#define concat4(x, y, z, w) concat3(concat(x, y), z, w)
|
||||
#define concat5(x, y, z, v, w) concat4(concat(x, y), z, v, w)
|
||||
|
||||
// macro testing
|
||||
// See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro
|
||||
#define CHOOSE2nd(a, b, ...) b
|
||||
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
|
||||
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
|
||||
// define placeholders for some property
|
||||
#define __P_DEF_0 X,
|
||||
#define __P_DEF_1 X,
|
||||
#define __P_ONE_1 X,
|
||||
#define __P_ZERO_0 X,
|
||||
// define some selection functions based on the properties of BOOLEAN macro
|
||||
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
|
||||
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
|
||||
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
|
||||
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_,macro, X, Y)
|
||||
|
||||
// test if a boolean macro is defined
|
||||
#define ISDEF(macro) MUXDEF(macro, 1, 0)
|
||||
// test if a boolean macro is undefined
|
||||
#define ISNDEF(macro) MUXNDEF(macro, 1, 0)
|
||||
// test if a boolean macro is defined to 1
|
||||
#define ISONE(macro) MUXONE(macro, 1, 0)
|
||||
// test if a boolean macro is defined to 0
|
||||
#define ISZERO(macro) MUXZERO(macro, 1, 0)
|
||||
// test if a macro of ANY type is defined
|
||||
// NOTE1: it ONLY works inside a function, since it calls `strcmp()`
|
||||
// NOTE2: macros defined to themselves (#define A A) will get wrong results
|
||||
#define isdef(macro) (strcmp("" #macro, "" str(macro)) != 0)
|
||||
|
||||
// simplification for conditional compilation
|
||||
#define __IGNORE(...)
|
||||
#define __KEEP(...) __VA_ARGS__
|
||||
// keep the code if a boolean macro is defined
|
||||
#define IFDEF(macro, ...) MUXDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
// keep the code if a boolean macro is undefined
|
||||
#define IFNDEF(macro, ...) MUXNDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
// keep the code if a boolean macro is defined to 1
|
||||
#define IFONE(macro, ...) MUXONE(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
// keep the code if a boolean macro is defined to 0
|
||||
#define IFZERO(macro, ...) MUXZERO(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
|
||||
// functional-programming-like macro (X-macro)
|
||||
// apply the function `f` to each element in the container `c`
|
||||
// NOTE1: `c` should be defined as a list like:
|
||||
// f(a0) f(a1) f(a2) ...
|
||||
// NOTE2: each element in the container can be a tuple
|
||||
#define MAP(c, f) c(f)
|
||||
|
||||
#define BITMASK(bits) ((1ull << (bits)) - 1)
|
||||
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
|
||||
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; (uint64_t)__x.n; })
|
||||
|
||||
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1))
|
||||
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz) - 1))
|
||||
|
||||
#define PG_ALIGN __attribute((aligned(4096)))
|
||||
|
||||
#if !defined(likely)
|
||||
#define likely(cond) __builtin_expect(cond, 1)
|
||||
#define unlikely(cond) __builtin_expect(cond, 0)
|
||||
#endif
|
||||
|
||||
// for AM IOE
|
||||
#define io_read(reg) \
|
||||
({ reg##_T __io_param; \
|
||||
ioe_read(reg, &__io_param); \
|
||||
__io_param; })
|
||||
|
||||
#define io_write(reg, ...) \
|
||||
({ reg##_T __io_param = (reg##_T) { __VA_ARGS__ }; \
|
||||
ioe_write(reg, &__io_param); })
|
||||
|
||||
#endif
|
||||
|
||||
*/
|
||||
6
game_engine/utils/ge_static_alloc.h
Normal file
6
game_engine/utils/ge_static_alloc.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __GE_STATIC_ALLOC_H__
|
||||
#define __GE_STATIC_ALLOC_H__
|
||||
|
||||
#include <ge_config.h>
|
||||
|
||||
#endif // __GE_STATIC_ALLOC_H__
|
||||
254
game_engine/utils/ge_vector2i.h
Normal file
254
game_engine/utils/ge_vector2i.h
Normal file
@@ -0,0 +1,254 @@
|
||||
#ifndef __GE_VECTOR2_H__
|
||||
#define __GE_VECTOR2_H__
|
||||
|
||||
|
||||
/**
|
||||
* @file ge_vector2i.h
|
||||
* @brief 2D整数向量库 (仿Godot Vector2i设计) 不依赖任何库的单文件
|
||||
* @defgroup Vector2 2D向量操作
|
||||
*/
|
||||
|
||||
// #define GE_VEC2I_USE_SHORT_NAMES
|
||||
|
||||
#ifdef GE_ABS
|
||||
#undef GE_ABS
|
||||
#define GE_ABS(x) ((x) > 0 ? (x) : -(x))
|
||||
#endif
|
||||
typedef int ge_unit_t; /**< 坐标值类型定义 */
|
||||
|
||||
/**
|
||||
* @struct ge_vector2_t
|
||||
* @brief 2D整数向量结构体
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
typedef struct {
|
||||
ge_unit_t x; /**< X轴坐标 */
|
||||
ge_unit_t y; /**< Y轴坐标 */
|
||||
} ge_vector2i_t;
|
||||
|
||||
// ========================= 构造函数 =========================
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I
|
||||
* @brief 创建向量 (x, y)
|
||||
* @param x_val X坐标值
|
||||
* @param y_val Y坐标值
|
||||
* @return 构造的向量
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I(x_val, y_val) ((ge_vector2i_t){(x_val), (y_val)})
|
||||
|
||||
// ========================= 常量定义 =========================
|
||||
|
||||
/** @def GE_VEC2I_ZERO 零向量 (0, 0) */
|
||||
#define GE_VEC2I_ZERO GE_VEC2I(0, 0)
|
||||
|
||||
/** @def GE_VEC2I_ONE 单位向量 (1, 1) */
|
||||
#define GE_VEC2I_ONE GE_VEC2I(1, 1)
|
||||
|
||||
/** @def GE_VEC2I_LEFT 左方向向量 (-1, 0) */
|
||||
#define GE_VEC2I_LEFT GE_VEC2I(-1, 0)
|
||||
|
||||
/** @def GE_VEC2I_RIGHT 右方向向量 (1, 0) */
|
||||
#define GE_VEC2I_RIGHT GE_VEC2I(1, 0)
|
||||
|
||||
/** @def GE_VEC2I_UP 上方向向量 (0, -1) */
|
||||
#define GE_VEC2I_UP GE_VEC2I(0, -1)
|
||||
|
||||
/** @def GE_VEC2I_DOWN 下方向向量 (0, 1) */
|
||||
#define GE_VEC2I_DOWN GE_VEC2I(0, 1)
|
||||
|
||||
// ========================= 运算宏定义 =========================
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_ADD
|
||||
* @brief 向量加法
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return a + b
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_ADD(a, b) GE_VEC2I((a).x + (b).x, (a).y + (b).y)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_SUB
|
||||
* @brief 向量减法
|
||||
* @param a 被减向量
|
||||
* @param b 减数向量
|
||||
* @return a - b
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_SUB(a, b) GE_VEC2I((a).x - (b).x, (a).y - (b).y)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_MUL
|
||||
* @brief 向量分量乘法
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return a * b (分量相乘)
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_MUL(a, b) GE_VEC2I((a).x * (b).x, (a).y * (b).y)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_DIV
|
||||
* @brief 向量分量除法
|
||||
* @param a 被除向量
|
||||
* @param b 除数向量
|
||||
* @return a / b (分量相除),如果分母为0会出现严重错误
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_DIV(a, b) GE_VEC2I( \
|
||||
(a).x / (b).x, \
|
||||
(a).y / (b).y \
|
||||
)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_DIV_SAFE
|
||||
* @brief 向量分量除法
|
||||
* @param a 被除向量
|
||||
* @param b 除数向量
|
||||
* @return a / b (分量相除),除零保护(分母为0返回0)
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_DIV_SAFE(a, b) GE_VEC2I( \
|
||||
(b).x ? (a).x / (b).x : 0, \
|
||||
(b).y ? (a).y / (b).y : 0 \
|
||||
)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_MUL_SCALAR
|
||||
* @brief 向量标量乘法
|
||||
* @param v 目标向量
|
||||
* @param s 标量值
|
||||
* @return v * s
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_MUL_SCALAR(v, s) GE_VEC2I((v).x * (s), (v).y * (s))
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_DOT
|
||||
* @brief 向量点积
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return a · b
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_DOT(a, b) ((a).x * (b).x + (a).y * (b).y)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_LENGTH_SQR
|
||||
* @brief 向量长度平方
|
||||
* @param v 目标向量
|
||||
* @return |v|²
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_LENGTH_SQR(v) (GE_VEC2I_DOT(v, v))
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_DISTANCE_SQR
|
||||
* @brief 两点间距离平方
|
||||
* @param a 起点向量
|
||||
* @param b 终点向量
|
||||
* @return |a - b|²
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_DISTANCE_SQR(a, b) GE_VEC2I_LENGTH_SQR(GE_VEC2I_SUB(a, b))
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_MIN
|
||||
* @brief 分量最小值
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return (min(a.x, b.x), min(a.y, b.y))
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_MIN(a, b) GE_VEC2I( \
|
||||
((a).x < (b).x) ? (a).x : (b).x, \
|
||||
((a).y < (b).y) ? (a).y : (b).y \
|
||||
)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_MAX
|
||||
* @brief 分量最大值
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return (max(a.x, b.x), max(a.y, b.y))
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_MAX(a, b) GE_VEC2I( \
|
||||
((a).x > (b).x) ? (a).x : (b).x, \
|
||||
((a).y > (b).y) ? (a).y : (b).y \
|
||||
)
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_CLAMP
|
||||
* @brief 分量钳制(钳制操作的意思是:如果某个分量小于最小值,
|
||||
* 则将其设置为最小值;如果大于最大值,则设置为最大值;
|
||||
* 如果在最小值和最大值之间,则保持不变。)
|
||||
* @param v 目标向量
|
||||
* @param min_vec 最小值向量
|
||||
* @param max_vec 最大值向量
|
||||
* @return 钳制后的向量
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_CLAMP(v, min_vec, max_vec) \
|
||||
GE_VEC2I_MIN(GE_VEC2I_MAX(v, min_vec), max_vec)
|
||||
|
||||
// ========================= 操作符 =========================
|
||||
/**
|
||||
* @def GE_VEC2I_EQUAL
|
||||
* @brief 判断两个向量是否相等(分量完全相等)
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return 1 表示相等,0 表示不相等
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_EQUAL(a, b) (((a).x == (b).x) && ((a).y == (b).y))
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_NOT_EQUAL
|
||||
* @brief 判断两个向量是否不相等
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @return 1 表示不相等,0 表示相等
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_NOT_EQUAL(a, b) (((a).x != (b).x) || ((a).y != (b).y))
|
||||
|
||||
/**
|
||||
* @def GE_VEC2I_APPROX_EQUAL
|
||||
* @brief 判断两个向量是否近似相等(在容忍度范围内)
|
||||
* @param a 第一个向量
|
||||
* @param b 第二个向量
|
||||
* @param tolerance 容忍度值
|
||||
* @return 1 表示近似相等,0 表示不近似相等
|
||||
* @note 对于整数向量,通常使用精确比较,但此宏提供了容忍度机制
|
||||
* @ingroup Vector2
|
||||
*/
|
||||
#define GE_VEC2I_APPROX_EQUAL(a, b, tolerance) \
|
||||
((GE_ABS((a).x - (b).x) <= tolerance) && \
|
||||
(GE_ABS((a).y - (b).y) <= tolerance))
|
||||
|
||||
// ========================= 可选前缀模式 =========================
|
||||
#ifdef GE_VEC2I_USE_SHORT_NAMES
|
||||
#define vec2i(x, y) GE_VEC2I(x, y)
|
||||
#define vec2i_zero GE_VEC2I_ZERO
|
||||
#define vec2i_one GE_VEC2I_ONE
|
||||
#define vec2i_add(a, b) GE_VEC2I_ADD(a, b)
|
||||
#define vec2i_sub(a, b) GE_VEC2I_SUB(a, b)
|
||||
#define vec2i_mul(a, b) GE_VEC2I_MUL(a, b)
|
||||
#define vec2i_mul_scalar(v, s) GE_VEC2I_MUL_SCALAR(v, s)
|
||||
#define vec2i_div(a, b) GE_VEC2I_DIV(a, b)
|
||||
#define vec2i_div_safe(a, b) GE_VEC2I_DIV_SAFE(a, b)
|
||||
#define vec2i_dot(a, b) GE_VEC2I_DOT(a, b)
|
||||
#define vec2i_length_sqr(v) GE_VEC2I_LENGTH_SQR(v)
|
||||
#define vec2i_min(a, b) GE_VEC2I_MIN(a, b)
|
||||
#define vec2i_max(a, b) GE_VEC2I_MAX(a, b)
|
||||
#define vec2i_clamp(v, min, max) GE_VEC2I_CLAMP(v, min, max)
|
||||
#define vec2i_equal(a, b) GE_VEC2I_EQUAL(a, b)
|
||||
#define vec2i_not_equal(a, b) GE_VEC2I_NOT_EQUAL(a, b)
|
||||
#define vec2i_approx_equal(a, b, tol) GE_VEC2I_APPROX_EQUAL(a, b, tol)
|
||||
#endif
|
||||
|
||||
#endif // __GE_VECTOR2_H__
|
||||
Reference in New Issue
Block a user