Simple Sprite Editor in J
摘要
本文介绍了如何在 J 语言中构建一个简单的精灵编辑器,涵盖窗口管理、网格绘制、键盘快捷键、鼠标绘图及调色板自定义等功能,展示交互式图形程序的核心技术。
<p><a href="https://lobste.rs/s/eitko7/simple_sprite_editor_j">Comments</a></p>
查看缓存全文
缓存时间: 2026/05/31 02:15
TL;DR: 本文介绍了如何在 J 语言中构建一个简单的精灵编辑器,涵盖窗口管理、网格绘制、键盘快捷键、鼠标绘图及调色板自定义等功能。
## 准备工作:窗口与关闭处理器
每个 J GUI 程序的第一步是编写窗口关闭处理器。将窗口命名为 `gpw`(grid pad window 的缩写),当点击关闭按钮时,J 自动查找 `gpw_close` 函数。处理器不会自动关闭窗口,允许执行确认、保存等操作。这里只需用窗口驱动命令选中窗口并关闭:
```j
wd 'parent select gpw parent close'
wd 'timer 0'
```
下方调用 `power` 连词控制运行次数,`wd 'parent'` 返回 0 或 1 表示窗口是否存在。若存在则关闭旧窗口。
## 窗口布局与渲染
通过窗口驱动调用 `wd` 设置界面。使用 `bin` 命令水平或垂直分组控件,创建左侧调色板、右侧画布和底部状态栏(不可见)。布局完成后需定义渲染函数 `render`:
```j
render =: 3 : 0
bm img;image [ wd 'psel ', gpw
)
```
这里导入 `viewmat`,调用 `bm` 将图像矩阵绘制到子控件中,并传入父控件名称 `gpw` 以确保绘图目标正确。之后每 100 毫秒调用一次 `render`(通过定时器);在调色板中则只在更改后显式重绘。
## 绘制网格
在 `render` 中添加网格绘制逻辑。由图像形状得到高、宽,查询画布控件的视口宽高,计算单元格大小,然后按行列生成线条位置:
```j
grid =: 3 : 0
shape =. $image
'w h' =. >3{ wd 'qchildxywhx ', img
cellsize =. (w,h) % |. shape
...
)
```
水平线和垂直线的绘制均使用 `glqchild` 获取视口尺寸,`+0.5 <.` 取整得到精确坐标。将窗口高度作为列表最后一项时,用波浪号 `~` 交换参数顺序使其成为动词。网格显示受键盘快捷键控制(见下节)。
## 键盘快捷键
每个控件独立拥有键盘事件处理器。命名规则:`gpw_pal_char` 和 `gpw_image_char` 均绑定同一动词,使键盘在任何控件获得焦点时都能响应。事件数据 `sysdata` 包含按键 ASCII 字符。定义快捷键:
- **G**:切换网格显示(`grid =: -. grid`)
- **R**:生成随机 32×32 24 位颜色网格(每个颜色 8 位红、绿、蓝)
- **N**:将所有像素重置为 0(黑色,新图像)
由于每秒重绘 10 次,按住 R 时展示动画效果。
## 鼠标交互:坐标映射与绘制
### 获取鼠标坐标
定义 `mmove` 事件处理器(画布专用)。`sysdata` 字符串包含鼠标事件信息,解析后前两个数字为相对于控件左上角的 x、y 坐标。
### 映射到数组索引
定义 `cellsize` 查询画布宽高并除以图像形状(注意数组 shape 为“高后宽”,需反转),得到每个单元格的像素大小。`whichbox` 函数从 `sysdata` 取前两个坐标,除以 `cellsize` 并向下取整,再反转坐标顺序(屏幕坐标 → 数组索引)。
```j
whichbox =: (|.@:<.@:(%~ |.))~
```
效果:鼠标上下移动时,第一个坐标(数组行索引)变化,第二个为列。
### 点击绘制
鼠标左键弹起事件 `mblup` 中调用 `mousedraw` 动词。`mousedraw` 使用 `amend` 副词(花括号 `{`)修改图像:将当前画笔颜色(十六进制值)插入到指定坐标位置。
重点:单一坐标需装箱(`<`),否则 J 会将二维数组索引视为一维索引(按行处理)。例如 `4 2 8` 会修改第 4 行和第 28 行的整个行。正确做法:
```j
mousedraw =: 3 : 0
image =: pen (< y) } image
)
```
## 连续绘制与边界检查
为支持鼠标按下时连续绘制,在 `mousemove` 处理器中检测左按钮是否按下(`sysdata` 的第四个元素)。若按下,则传递给 `mousedraw`。
拖拽至画布外时,鼠标事件仍会报告超出范围的坐标,导致数组索引越界。加上边界检查:
```j
inbounds =: 4 : ' *./ (0<:x) *. (x < y)'
```
用 `inbounds image` 包裹 `mousedraw` 调用,确保坐标在每个维度上 ≥0 且 < 对应大小。
## 调色板与颜色选择
调色板是一维颜色数组,默认使用 90 年代 ZZT 艺术的 16 色标准。垂直渲染时,使用 `,.` 将每个元素变成单独的行(二维数组)。定义调色板绘制事件处理器,但未接入定时器,仅在窗口重绘时生效。
画笔颜色通过变量 `pen`(调色板索引)存储。更新 `mousedraw` 使用 `pen` 而非固定值,实现不同颜色绘制。
## 总结
本文完整演示了在 J 语言中构建一个具备基本功能的精灵编辑器。从窗口管理、渲染绘图、鼠标键盘事件处理到自定义调色板,涵盖了构建交互式图形程序的核心技术。代码可在 J 环境中直接运行,作为进一步开发的基础。
Source: [YouTube 视频链接](https://www.youtube.com/watch?v=CzK2SazvCxM)
相似文章
@0xQiYan: 还在手动画架构图?拖来拖去改半天? 收藏!今天必须安利这个skill——我最近装了个 `drawio-skill`,一句话就能生成专业图表,再也不用自己画了。 它的逻辑特别简单:你只用说人话(比如“画一个交易系统架构图”),它直接给你生成…
介绍 drawio-skill 工具,通过自然语言描述即可生成架构图、流程图、ER图等专业图表,支持多轮迭代和导出多种格式,大幅提升画图效率。
@VincentLogic: 发现个科研绘图神器! nature-skills,用 matplotlib 就能画出 Nature 级别的图。多面板布局、配色、字体、排版都给你整得明明白白,直接输出可编辑的 SVG。 内置了 5 套 Nature 风格的示例模板,支持柱…
nature-skills 是一个基于 matplotlib 的科研绘图工具,内置 Nature 风格模板,支持多种图表类型并输出可编辑的 SVG 格式,旨在简化科研论文的图表制作流程。
@VincentLogic: 发现个前端圈公认的动画神器,68K stars 真的不是吹的! anime.js —— 一个轻量级但功能极其强大的 JavaScript 动画引擎。 前端兄弟们又来享福了,这玩意儿简直是“动画师的瑞士军刀”: 全能型选手 不管是 CSS …
Anime.js 是一个轻量级但功能强大的 JavaScript 动画引擎,支持 CSS、SVG、DOM 属性及 JavaScript 对象动画,具有直观的 API、时间线系统、滚动观察器、拖拽和响应式动画等特性,在 GitHub 上拥有 68K stars,是前端开发者和交互设计师的常用工具。
SPRITE:从静态设计稿到引擎就绪的游戏 UI
SPRITE 提出一套流程,利用视觉-语言模型与 YAML 中间格式,将静态游戏 UI 截图转换为可编辑的引擎资源,自动处理复杂布局与深层嵌套。
@VincentLogic: 发现个字节开源的桌面 AI 神器! UI-TARS Desktop,31k stars 不是吹的,这玩意儿真能看懂你的屏幕,然后帮你自动操作电脑。 你告诉它"帮我把 VS Code 的自动保存打开,延迟改成 500 毫秒",它就自己: -…
字节跳动开源的桌面 AI 自动化工具 UI-TARS Desktop 支持本地运行与屏幕视觉理解,可通过自然语言指令自主操控电脑完成日常任务。