news 2026/8/6 2:52:39

Linux文件创建全攻略:从touch到vim的实战场景解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux文件创建全攻略:从touch到vim的实战场景解析

1. 从零开始:为什么我们需要掌握多种创建文件的方式?

在Linux世界里,文件是操作系统与用户交互最核心的载体。无论是编写一个脚本、记录一段日志、还是配置一个服务,第一步往往都是创建一个文件。很多刚接触Linux的朋友,可能只知道一两种创建文件的方法,比如用touch或者vi。但当你真正深入到日常运维、开发或者系统管理时,你会发现,不同的创建方式背后,对应着截然不同的使用场景和效率考量。它不仅仅是“创建一个空文件”这么简单,而是关于“如何高效地、符合场景地初始化你的工作环境”。

举个例子,你需要在脚本中动态生成一个配置文件,你会选择打开vi然后手动输入吗?显然不会。你需要的是一个命令,能直接将文本内容写入文件。又或者,你只是想快速创建一个占位符文件,用来测试磁盘空间或者作为某个任务的触发标志,这时候打开一个编辑器就显得大材小用了。因此,熟练掌握touchechocatvi/vim这几种创建文件的方式,是每个Linux使用者从“会用”到“用好”的关键一步。这几种工具覆盖了从简单空文件创建、到内容直接写入、再到交互式编辑的全场景需求。理解它们之间的区别和最佳实践,能让你在命令行下的工作效率提升一个档次。接下来,我们就抛开那些笼统的教程,从实际应用的角度,把这几种方式掰开揉碎了讲清楚。

2. 核心工具深度解析与应用场景抉择

在深入具体命令之前,我们有必要先建立一个宏观的认识。这几种命令虽然都能“创建文件”,但它们的核心设计目的、工作模式以及适用场景有着本质的不同。选择哪种方式,取决于你的初始意图:你是要一个空的文件壳子,还是要立刻写入内容?内容是简单的一行还是复杂的多行?是否需要立刻编辑?

2.1touch:纯粹的“造壳者”

touch命令的本意是修改文件的时间戳(访问时间、修改时间)。如果文件不存在,它就顺带创建一个空文件。这个特性让它成为了创建空文件最直接、最快速的工具。

核心原理与参数: 它的工作逻辑非常简单:检查目标路径是否存在同名文件。如果存在,则将其访问时间(atime)和修改时间(mtime)更新为当前时间(或指定时间)。如果不存在,则直接创建一个字节数为0的空文件,并设置相应的时间戳。

常用参数:

  • -a: 仅更改访问时间。
  • -m: 仅更改修改时间。
  • -c--no-create:关键参数。如果文件不存在,则不创建。这个参数在你只想更新时间戳而避免意外创建文件时非常有用。
  • -t: 使用指定的时间戳,格式为[[CC]YY]MMDDhhmm[.ss]

典型应用场景

  1. 批量创建占位文件:在测试脚本或构建目录结构时非常有用。
    # 创建一系列日志空文件 touch app_{20231001..20231005}.log
  2. 作为任务完成的标志文件:很多自动化流程(如CI/CD)会通过检查某个标志文件是否存在来判断上一步是否完成。touch done.flag比写入内容更安全、意图更清晰。
  3. 重置或伪造文件时间:用于某些对文件时间有特殊要求的场景,比如让make认为源文件已“更新”从而触发重新编译。
    touch source.c # 假装source.c被修改了 make

注意touch创建的文件是真正的空文件,其大小是0字节。用ls -l查看时,文件大小显示为0。这与某些编辑器创建的、可能包含换行符的“空文件”有细微差别。

2.2echo:单行内容的快速写入器

echo命令用于向标准输出打印一行文本。通过Shell的重定向功能(>>>),我们可以轻松地将这行文本写入文件,从而在创建文件的同时赋予其初始内容。

核心原理与重定向echo本身不操作文件,它只负责生成文本流。创建文件的行为是由重定向操作符完成的。

  • >:输出重定向。如果文件不存在则创建,如果存在则清空原有内容后写入。
  • >>:追加重定向。如果文件不存在则创建,如果存在则在末尾追加新内容。

典型应用场景

  1. 快速创建简单配置文件或脚本头
    echo '#!/bin/bash' > myscript.sh echo '# This is a backup script' >> myscript.sh chmod +x myscript.sh
  2. 动态生成内容文件:在脚本中,结合变量生成文件内容。
    user_name="alice" echo "Welcome, $user_name! Login time: $(date)" > welcome.txt
  3. 写入特殊字符或变量:需要注意引号的使用。单引号会原样输出,双引号会解释变量和部分转义字符。
    # 双引号,$USER会被替换 echo "User is $USER" > file1.txt # 单引号,$USER会作为普通字符串 echo 'User is $USER' > file2.txt # 写入多行(使用-e启用转义,\n表示换行) echo -e "Line 1\nLine 2\nLine 3" > multiline.txt

实操心得:使用echo>时要格外小心,因为它会无条件覆盖同名文件。一个良好的习惯是,在不确定文件是否存在或内容重要时,先使用ls确认,或者使用set -o noclobber(在bash中)设置选项来防止覆盖,此时使用>会报错,必须使用>|来强制覆盖。

2.3cat与重定向:多行内容的流式构造器

cat(concatenate的缩写)命令的本意是连接文件并输出。但它结合Here Document(<<)语法,成为了从命令行直接创建并写入多行内容的神器,无需调用外部编辑器。

核心原理:Here DocumentHere Document是一种Shell的输入重定向,它允许在命令行中嵌入一段文本块,并将其作为标准输入传递给命令。语法是命令 << 结束标记,之后输入内容,最后在单独一行写上结束标记。

典型应用场景

  1. 创建内容较多的配置文件:比如快速创建一个Nginx或Docker的简易配置。

    cat > docker-compose.yml << 'EOF' version: '3.8' services: web: image: nginx:alpine ports: - "80:80" db: image: postgres:13 environment: POSTGRES_PASSWORD: secret EOF

    注意,上例中EOF被单引号包裹,表示结束标记内的变量(如$POSTGRES_PASSWORD)不会被Shell解释。如果去掉单引号,变量会被展开。

  2. 在脚本中生成模板文件:这是Shell脚本中最优雅的生成文件方式之一,可读性远高于多个echo命令。

    #!/bin/bash CONFIG_FILE="/tmp/app.conf" cat > $CONFIG_FILE << _EOF_ # Auto-generated config server_ip=${SERVER_IP:-127.0.0.1} server_port=${SERVER_PORT:-8080} log_level=INFO _EOF_ echo "Configuration generated at $CONFIG_FILE"
  3. 合并创建与内容追加:虽然不常见,但cat也可以先读入一个Here Document,再追加到文件。

    cat >> existing.log << END [$(date)] Application started a new cycle. END

注意事项:Here Document的结束标记必须顶格写,且前后不能有任何字符(包括空格)。如果内容里包含制表符,可以使用<<-来忽略内容行首的制表符(Tab),但空格不行,这常用于美化脚本中的缩进。

2.4vi/vim:全功能的交互式编辑器

vi(及其增强版vim)是Linux系统中最经典、最强大的终端文本编辑器。它通过全屏交互模式来创建和编辑文件。与前面所有命令的本质区别在于,它是一个交互式环境,创建文件只是其功能的起点。

核心模式解析vim的成功在于其模式化设计,新手感到困惑也往往源于此。

  1. 普通模式:打开文件后的默认模式。在此模式下,所有按键都是命令,用于移动光标、删除、复制、粘贴等。这是vim的指挥中心
  2. 插入模式:在此模式下,你可以像使用普通记事本一样输入文本。按iao等键从普通模式进入。
  3. 命令行模式:在普通模式下按:进入,可以执行保存、退出、搜索、替换等复杂命令。

典型应用场景

  1. 创建并编辑全新的复杂文件:如编写程序源代码、Markdown文档、复杂的系统配置等。

    vim new_script.py

    进入后,按i进入插入模式开始编写,写完按Esc回到普通模式,再输入:wq保存并退出。

  2. 修改现有文件:这是vim的日常。它允许你进行极其高效的精准编辑。

  3. 无交互式创建(高级技巧)vim其实也支持非交互式创建/写入文件,但这通常不是最佳实践。例如,可以使用ex模式(vim的前身):

    # 创建一个包含一行内容的文件(不进入交互界面) ex -s -c 'echo "Hello"' -c 'wq' newfile.txt

    不过,这种场景下,使用echocat显然更简单直接。

避坑技巧:对于新手,最常遇到的“坑”就是打开vim后不知道怎么输入或怎么退出。记住这个最小工作流:1) 用vim filename打开文件。2) 按i键开始插入文本。3) 编辑完成后,按Esc键退出插入模式,回到普通模式。4) 输入:wq(冒号wq)然后按回车,表示入并退出。如果不想保存,则输入:q!

3. 实战对比与情景化操作指南

了解了每个工具的“个性”后,我们通过一系列具体的工作场景,来对比如何选择最合适的工具,并给出详细的操作步骤。

3.1 场景一:初始化项目目录结构

任务:你需要为一个新的Web项目创建标准的目录树:project/{public, src, tests, logs},并在logs目录下预先创建本月的日志空文件。

分析与选型

  • 创建空目录:使用mkdir -p
  • 创建空日志文件:这是典型的“占位”需求,使用touch最合适,因为它最快、意图最明确。

实操步骤

# 1. 创建项目根目录及子目录 mkdir -p project/{public,src,tests,logs} # 2. 进入logs目录 cd project/logs # 3. 获取当前年月,并创建当月的日志文件(例如2023-10-01到2023-10-31) current_year=$(date +%Y) current_month=$(date +%m) # 使用touch批量创建,利用序列生成 touch app_${current_year}-${current_month}-{01..31}.log # 4. 返回上级目录,验证结果 cd .. find . -type f -name "*.log" | head -5 # 查看前5个创建的日志文件

关键点解析

  • mkdir -p中的-p参数确保可以创建多级目录,且如果目录已存在也不会报错。
  • {01..31}是Bash的大括号扩展,它会自动展开为01, 02, ..., 31的序列。如果当月没有31天,比如2月,touch会创建失败,但不会影响已创建的文件。更严谨的做法是根据月份计算天数,但此例中touch的容错性可以接受。
  • 使用$(date +%Y)$(date +%m)命令替换来动态获取年月,使脚本具有通用性。

3.2 场景二:编写一个自动化部署脚本

任务:编写一个Shell脚本deploy.sh,该脚本需要包含多行注释、变量定义和一系列命令。

分析与选型

  • 这是一个需要创建包含复杂多行文本的文件。
  • 虽然可以用vim交互式编写,但在自动化或需要清晰记录生成过程的场景下,使用cat配合 Here Document 是更优选择。它能让脚本的生成逻辑一目了然,也便于在脚本中嵌套生成其他脚本。

实操步骤

# 直接在终端中执行以下命令来创建脚本 cat > deploy.sh << 'SCRIPT_EOF' #!/bin/bash # ============================================ # 自动化部署脚本 # 作者:运维团队 # 日期:$(date +%Y-%m-%d) # ============================================ # 配置区域 readonly DEPLOY_USER="appuser" readonly TARGET_DIR="/opt/myapp" readonly BACKUP_DIR="/backup/$(date +%Y%m%d_%H%M%S)" readonly JAR_FILE="target/myapp-*.jar" # 颜色输出函数 green_echo() { echo -e "\033[32m[INFO] $*\033[0m"; } red_echo() { echo -e "\033[31m[ERROR] $*\033[0m"; } # 主函数 main() { green_echo "开始部署流程..." # 1. 备份现有版本 if [ -d "$TARGET_DIR" ]; then green_echo "备份现有应用到 $BACKUP_DIR" mkdir -p "$BACKUP_DIR" cp -r "$TARGET_DIR"/* "$BACKUP_DIR"/ 2>/dev/null || true fi # 2. 停止现有服务(假设通过systemctl管理) green_echo "停止应用服务..." systemctl stop myapp-service 2>/dev/null || red_echo "服务停止失败或未运行,继续..." # 3. 清理并部署新文件 green_echo "部署新版本..." rm -rf "${TARGET_DIR:?}"/* # 这里假设jar包已经在当前目录 cp $JAR_FILE "$TARGET_DIR"/myapp.jar cp -r config/ "$TARGET_DIR"/ # 4. 启动服务 green_echo "启动应用服务..." systemctl start myapp-service systemctl status myapp-service --no-pager green_echo "部署完成!" } # 脚本入口 if [[ "${BASH_SOURCE[0]}" = "${0}" ]]; then main "$@" fi SCRIPT_EOF # 创建后,赋予执行权限 chmod +x deploy.sh

关键点解析

  • 使用<< 'SCRIPT_EOF',单引号保证了Here Document内的所有内容(包括$(date))在创建deploy.sh文件时都不会被解释,而是原封不动地写入。这样,脚本内部的$(date +%Y-%m-%d)会在执行deploy.sh时被计算,而不是在创建时。
  • 脚本内容包含了Shebang、注释、变量、函数、流程控制,是一个结构良好的Shell脚本模板。
  • cprm命令中使用了${TARGET_DIR:?},这是一种安全写法,如果TARGET_DIR变量为空或未设置,脚本会立即报错退出,防止误删根目录等灾难性操作。

3.3 场景三:快速记录一条命令的输出到新文件

任务:检查系统负载,并将结果保存到一个以当前时间戳命名的日志文件中。

分析与选型

  • 需要将一条命令的输出直接存入文件。
  • 这是标准输出重定向(>)的经典场景。通常与echo添加标题,或直接使用命令组合。

实操步骤

# 方案1:直接保存命令输出 uptime > system_uptime_$(date +%s).log # 方案2:添加一些上下文信息再保存 { echo "====== System Status Snapshot ======" date echo "-----------------------------------" uptime echo "-----------------------------------" free -h | head -2 # 查看内存使用概况 } > system_status_$(date +%Y%m%d_%H%M%S).log # 查看生成的文件 ls -lh system_*.log cat system_status_*.log

关键点解析

  • $(date +%s)生成Unix时间戳(秒级),$(date +%Y%m%d_%H%M%S)生成更易读的日期时间字符串,用于保证文件名唯一。
  • 方案2中使用了命令组{ ... },将多个命令的输出合并后,一次性重定向到同一个文件,这比分别重定向每个命令更高效,也保证了内容的连续性。
  • free -h | head -2只取内存信息的前两行(标题和总计行),使日志更简洁。

4. 进阶技巧、常见陷阱与排查指南

掌握了基本操作后,一些进阶技巧和“坑”能让你更加游刃有余。

4.1 权限与所有权问题

创建文件时,文件的默认权限和所有者是由什么决定的?

  • 权限:受当前Shell的umask值影响。新文件的权限通常是666(rw-rw-rw-)减去umask值。常见的umask022,那么创建的文件权限就是644(rw-r--r--)。你可以用umask命令查看和临时修改。
    umask # 查看当前umask umask 027 # 临时设置为027,则新建文件权限为640 (rw-r-----) touch newfile_with_umask ls -l newfile_with_umask
  • 所有者与属组:文件的所有者是执行创建命令的用户,属组是该用户的主要组。如果需要以其他用户身份创建文件,需要使用sudo或切换用户。
    sudo touch /root/admin_file.txt # 文件所有者为root sudo -u www-data touch /var/log/app.log # 以www-data用户身份创建

常见问题:使用sudo创建的文件,后续用普通用户编辑可能会遇到权限不足。一个常见的做法是创建后修改所有权:

sudo touch /opt/app/config.yaml sudo chown $USER:$USER /opt/app/config.yaml # 将所有者改回当前用户

4.2 关于“空文件”的微妙区别

touch创建的是物理上0字节的文件。而某些编辑器或重定向方式可能会创建“非纯粹”的空文件。

# 创建一个真正0字节的文件 touch pure_empty.txt # 使用echo重定向一个空字符串,注意-n参数避免添加换行符 echo -n > echo_empty.txt # 使用vim创建并立刻退出的“空文件”,可能包含一个换行符 vim vim_empty.txt # 进入后直接输入 :wq # 使用cat从空输入创建 cat /dev/null > cat_empty.txt # 使用hexdump或wc查看区别 wc -c *.txt # 查看字节数 hexdump -C vim_empty.txt # 可能会看到文件末尾的0a(换行符)

对于大多数应用,这种差别无关紧要。但在极少数对文件内容哈希值或精确大小有严格要求的场景(例如某些加密或校验场景),需要意识到这一点。

4.3 覆盖与追加的误操作风险

echo “text” > filecat > file << EOF中的>操作符是“沉默的杀手”。如果file已存在且有重要内容,它会被毫无警告地覆盖。

防护策略

  1. 设置noclobber选项(在bash/zsh中有效):
    set -o noclobber # 开启防覆盖 echo "test" > existing_file # 会报错:bash: existing_file: cannot overwrite existing file echo "test" >| existing_file # 使用 >| 强制覆盖 set +o noclobber # 关闭防覆盖
  2. 先备份再操作:在脚本中,对重要文件进行操作前先备份。
    [[ -f config.conf ]] && cp config.conf config.conf.bak.$(date +%s) echo "new config" > config.conf
  3. 使用更安全的命令:对于简单的追加,>>是安全的。对于复杂的覆盖,可以考虑先用mv重命名旧文件。

4.4 文件编码与特殊字符

当使用echocat创建包含特殊字符的文件时,需要注意字符转义和编码。

  • 换行符:Unix/Linux使用\n(LF),Windows使用\r\n(CRLF)。在脚本中创建文件时,默认是LF。如果文件需要在Windows下使用,可能需要转换。
  • 变量扩展:在Here Document中,如果结束标记不加引号,$VAR$(command)`command`都会被Shell扩展。如果希望原样写入这些符号,必须给结束标记加单引号。
    # 变量会被扩展 cat > expanded.txt << EOF My home is $HOME EOF # 变量会原样写入 cat > literal.txt << 'EOF' My home is $HOME EOF
  • 制表符与空格:在Here Document中,行首的缩进如果不想被保留,可以使用<<-并配合Tab键(不是空格)。
    cat > script.sh <<- 'EOF' #!/bin/bash if true; then echo "Indented with tabs" fi EOF # 文件内容中的行首Tab会被去除,但行内的Tab保留

4.5 性能考量与大批量操作

在需要创建成千上万个文件的极端场景下(例如,压力测试、模拟海量小文件),不同命令的性能有差异。

  • touch:是最高效的,因为它的系统调用最直接。
  • echo >:涉及Shell启动子进程和重定向管理,比touch稍慢。
  • cat << EOF >:涉及Here Document解析,开销更大。
  • vim:启动一个完整的编辑器进程,开销最大,绝对不适合批量操作。

大批量创建优化示例

# 低效方式:在循环中反复调用命令 for i in {1..10000}; do echo "content" > "file_${i}.txt" done # 高效方式:尽量减少命令调用次数 # 使用printf和xargs并行处理 printf "file_%s.txt\n" {1..10000} | xargs -P 8 -I {} sh -c 'echo "content" > {}' # 或者,如果只是创建空文件,用touch配合xargs printf "file_%s.txt\n" {1..10000} | xargs touch

xargs-P参数可以指定并行进程数,能极大提升批量操作速度。

5. 工具链整合与创造性用法

真正的高手,不会孤立地使用这些命令,而是将它们组合起来,融入自己的工作流。

5.1 组合使用:创建并立即编辑

有时我们需要创建一个有初始模板的文件,并立刻开始编辑。一种优雅的方式是组合catvim

# 先创建一个带有基本模板的Python脚本 cat > new_script.py << 'PYTHON_EOF' #!/usr/bin/env python3 """ Module: new_script Author: $(whoami) Created: $(date +%Y-%m-%d) """ import sys import logging def main(): # TODO: Implement main logic pass if __name__ == "__main__": main() PYTHON_EOF # 然后立即用vim打开它进行编辑 vim new_script.py

你可以将这个过程封装成一个Shell函数,放到你的~/.bashrc中:

newpy() { local filename=$1 cat > "$filename" << 'TEMPLATE_EOF' #!/usr/bin/env python3 """ Module: ${filename%.py} Author: $(whoami) """ def main(): print("Hello from ${filename%.py}!") if __name__ == "__main__": main() TEMPLATE_EOF chmod +x "$filename" ${EDITOR:-vim} "$filename" # 使用$EDITOR环境变量指定的编辑器,默认为vim }

这样,你只需要输入newpy my_cool_tool.py,就能一键获得一个带模板的可执行Python文件并进入编辑状态。

5.2 从模板生成配置文件

在DevOps中,经常需要根据环境变量生成不同的配置文件。cat+ Here Document + 环境变量替换是绝配。

# 假设有以下环境变量 export DB_HOST="prod-db.example.com" export DB_PORT="5432" export DB_NAME="myapp_prod" # 从模板生成配置 cat > application.properties << CONFIG_EOF # Database Configuration spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME} spring.datasource.username=${DB_USER:-myapp_user} spring.datasource.password=${DB_PASSWORD:?DB_PASSWORD environment variable must be set} # Server Configuration server.port=8080 logging.level.com.myapp=INFO CONFIG_EOF

这里使用了Bash的变量替换语法:

  • ${VAR:-default}:如果VAR未设置或为空,则使用default值。
  • ${VAR:?error_message}:如果VAR未设置或为空,则打印error_message并退出脚本。这是一种严格的参数检查。

5.3 使用tee命令同时创建和查看

tee命令像一个“T型三通”,它从标准输入读取数据,同时写入文件和标准输出。这在创建文件的同时还想看到内容时非常有用。

# 将系统信息同时写入文件和屏幕 { echo "=== System Report ===" date uname -a df -h / } | tee system_report.txt # 在需要sudo权限的目录创建文件并查看 echo "新的配置项" | sudo tee /etc/myapp/conf.d/new_setting.conf > /dev/null # 使用tee和sudo时,管道左边的命令不需要sudo,只有tee本身需要

tee -a命令可以实现追加模式,相当于>>

掌握这些创建文件的方法,远不止是记住几个命令。它体现的是你对Linux哲学“一个工具只做好一件事”和“通过组合工具解决问题”的理解。从最简单的touch到最复杂的vim宏,每一种方法都在其特定的场景下散发着光芒。下次当你需要创建一个文件时,不妨先花一秒钟思考一下:“我真正的需求是什么?” 然后选择那把最合适的“钥匙”。这种思考习惯,才是提升命令行效率的真正秘诀。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/6 2:51:11

LLM应用日志脱敏实战:从正则到NER的混合方案与工程架构

1. 项目概述&#xff1a;当LLM日志成为隐私泄露的“后门”最近在排查一个线上LLM应用的问题时&#xff0c;我翻看Trace日志&#xff0c;里面赫然躺着用户输入的完整身份证号和家庭住址。那一刻&#xff0c;后背有点发凉。我们花大力气在模型前端做输入过滤、在输出端做内容安全…

作者头像 李华
网站建设 2026/8/6 2:49:22

二叉树前中后序遍历

二叉树前中后序遍历 - 代码实现思路与图解 1. 项目概述 本项目实现了二叉树的三种遍历方式&#xff1a;前序遍历、中序遍历和后序遍历&#xff0c;均采用递归实现。 2. 数据结构定义 2.1 二叉树节点结构 typedef char BTDataType;typedef struct BinaryTreeNode {struct Binary…

作者头像 李华
网站建设 2026/8/6 2:45:33

物理乒乓(Pong 风格

&#xfeff;「赛博原力&#xff1a;物理乒乓&#xff08;Pong 风格 / 刚体线圆碰撞、摩擦力矩赋予与智能轨迹拦截&#xff09;」。这次我们将攻克 2D 对抗游戏中最核心的物理技术——「线段与圆形动态刚性碰撞计算&#xff08;Line-Circle Intersection&#xff09;、挡板移动…

作者头像 李华
网站建设 2026/8/6 2:44:36

Unity网格平滑与优化插件:从硬边到光滑的工程实践

1. 项目概述&#xff1a;为什么我们需要一个网格平滑与优化插件&#xff1f;在Unity开发中&#xff0c;尤其是涉及美术资源导入和优化的环节&#xff0c;我们经常会遇到一个经典的两难问题&#xff1a;性能与视觉质量的权衡。美术同学从3ds Max、Blender或Maya中导出的模型&…

作者头像 李华
网站建设 2026/8/6 2:44:32

物理台球(8 Ball Pool 风格

&#xfeff;「赛博原力&#xff1a;物理台球&#xff08;8 Ball Pool 风格 / 刚体球球对心碰撞、白球母球击打与轨道微擦同化&#xff09;」。前面我们写过了旋转多米诺、矩形叠叠乐和刚体连缀蛇&#xff0c;这次我们将攻克 2D 物理游戏中最优雅且极具技术含量的硬核技术——「…

作者头像 李华