第四十七章 48小时极限赶工
利普像一具被抽乾了灵魂的行尸走肉,步履蹣跚地走下台阶。背后那扇代表著温暖与希望的大门,已经彻底对他关闭。
没有了这800美金的尾款,马库斯的棒球棍將在周末无情地砸碎他的双手,而东欧黑帮则会把他的弟弟妹妹切成零件卖到黑市。
绝望,一种真正令人窒息的绝望,如附骨之疽般爬满了他全身。他甚至想过要不要去抢劫街角的便利店,或者去偷弗兰克的藏身处,但那些念头在脑海中闪过的瞬间就被他自己否定了。
钱不够,也来不及。
就在利普深一脚浅一脚地踩在满是积水的柏油马路上,准备迎接死亡的审判时。
“咔噠。”
身后,杨坚家那扇沉重的大门突然再次被人推开。一道暖黄色的灯光像利剑一样劈开了漆黑的街道,正好照在利普单薄的背影上。
利普浑身一震,猛地回过头。
杨坚依旧穿著那件单薄的短袖,双手抱在胸前,居高临下地站在门廊的台阶上。夜风吹动他额前的碎发,那双深邃的黑眸里没有任何怜悯,只有属於理智的绝对冷酷。
“啪嗒。”
一个沉甸甸的黑色塑胶袋被杨坚隨手扔了出来,精准地砸在利普脚边的水坑旁。
利普愣住了,他如同抓住救命稻草般死死盯著那个袋子,却不敢轻举妄动。
“我刚才说过了,我不做廉价的慈善,更不会无缘无故替你擦屁股。”杨坚的声音穿透冷风,清晰地砸进利普的耳朵里,“但我是一个生意人,我愿意给你一个证明自己价值,顺便完成自救的交易。”
利普猛地抬头,他几乎是连滚带爬地扑回台阶前,死死盯著杨坚:“什么交易?只要能拿到钱,我什么都干!”
杨坚指了指地上的袋子,语气毫无波澜:“你的游戏代码,距离完整交付还差整整一个星期的工作量。现在,捡起那个袋子。里面有两瓶足够让你心臟狂跳的阿德拉(adderall)提神药片,还有五罐能苦到让你舌头髮麻的黑咖啡。”
利普低头看了一眼那个袋子,脸上神色带有疑惑,显然还没反应过来。
“利普,你看过《社交网络》这部电影吗?”杨坚突然拋出了一个看似毫不相干的问题。
利普愣了一下,呆呆地点了点头。那部讲述facebook创始人发家史的电影前不久刚上映,他在电影院里偷偷溜进去看过。
“很好。”杨坚嘴角勾起一抹冰冷的弧度,“既然看过,那你就应该知道,那些改变世界的极客,在面临生死存亡的节点时是怎么做的。”
杨坚微微前倾身体,压迫感如泰山压顶般袭来:“我要你像马克·扎克伯格一样!把你那可笑的自尊心扔进垃圾桶,把自己死死锁在房间里!磕著药,喝著烂咖啡,两耳不闻窗外事,熬夜拼命把这个项目给我敲出来!”
“从现在起,我只给你四十八个小时!”
杨坚抬起手腕,看了一眼錶盘,声音如同死神的倒计时:“今天是周一晚上五点。周三下午五点之前,把剩下一周的活全部给我完美干完!如果没有致命bug,代码能顺利跑通,我就会把游戏打包上线。只要游戏上线,我就立刻结清你的尾款。”
他俯视著这个因为恐惧和激动而浑身发抖的南区天才:“如果你能在48小时內把现在的半成品变成完整版,你的手就保住了。如果干不完,或者你交给我的是一坨满是bug的屎……”
杨坚顿了顿,眼神变得无比森寒:“我就坐在这里,喝著热咖啡,透过窗户亲眼看著那帮大猩猩把你的手指一根、一根地掰断。”
“砰!”
大门再次重重关上,將所有的温暖与灯光重新隔绝。
但这一次,站在冷风中的利普没有再感到绝望。他猛地扑向地上的黑色塑胶袋,像护著稀世珍宝一样將里面的药片和咖啡死死抱在怀里。
那是他的命!那是他双手和家人的命!
利普深吸了一口冰冷的空气,原本因为恐惧而涣散的眼神,此刻爆发出一种如同饿狼般的凶狠光芒。他转身,迈开双腿,像疯了一样朝著加拉格家那栋破旧的房子狂奔而去。
……
“砰!”
利普一脚踹开自己臥室的房门,反手將其死死反锁。
隔壁房间里,菲奥娜还在因为俄罗斯黑帮的恐嚇而无助地哭泣,黛比和卡尔在楼下因为抢夺最后半块发硬的麵包而大声爭吵。整个加拉格家依然笼罩在一片混乱与末日般的压抑中。
但这一切,此刻都被利普彻底屏蔽了。
他一把扫开书桌上那些乱七八糟的杂物,將那台破旧的二手笔记本电脑小心翼翼地放在桌面上。按下开机键,屏幕亮起微弱的萤光,照亮了他那张因为极度紧张而微微抽搐的脸。
他撕开塑胶袋,拧开一瓶阿德拉,倒出两片白色的药丸,连水都没喝,直接仰起头生咽了下去。接著,他拉开一罐黑咖啡,“吨吨吨”地灌了半罐。
苦涩的液体顺著食道流下,伴隨著药效的发作,他的心臟开始加速跳动,大脑仿佛被注入了高压电流,瞬间从疲惫中清醒过来,精神亢奋到了极点。
“四十八小时……一个星期的工作量……我能做到,我他妈是个天才,我他妈一定能做到!”
利普神经质般地喃喃自语著,双手如同抽筋般猛地放在键盘上。
“啪嗒啪嗒啪嗒——”
键盘的敲击声如同暴雨般在狭小冰冷的臥室里炸响。
这是利普人生中第一次,真正意义上体验到了科技网际网路圈子里臭名昭著、折磨人的词汇——项目衝刺。
没有了平日里那种写两行代码就去抽根烟、喝口酒的散漫。
在生死存亡的倒计时面前,他彻底拋弃了所有的南区小聪明,他不再去想怎么偷车,不再去想怎么代考,他现在的世界里,只有屏幕上那些跳动的字符、模块、对象和逻辑判断。
周一的深夜,冷风顺著窗户的缝隙呼啸著灌进房间,冻得他双手发僵。他只能每隔半小时就把手放在大腿下捂热,然后再继续疯狂敲击。
ui界面的渲染、滑动逻辑的边界判定、分数翻倍的算法优化、存储最高分的本地缓存……那些原本需要大量时间去构思和调试的底层逻辑,在他的大脑超负荷运转下,被强行压缩成一行行密集的代码。
到了周二的中午,药效开始减退。一种仿佛要將灵魂撕裂的疲惫感如潮水般涌来。利普的眼皮像灌了铅一样沉重,眼前屏幕上的代码开始出现重影,字母仿佛变成了乱爬的蚂蚁。
“利普!你在里面干什么?出来吃点东西!”门外传来菲奥娜带著哭腔的敲门声,“马库斯刚才又打电话来威胁了,我们该怎么办啊……”
“別管我!別打扰我!”
利普发出野兽般的低吼。他用发抖的手再次拧开药瓶,倒出药片塞进嘴里,用冰冷的黑咖啡冲服下去。
周二的夜晚,是最难熬的地狱。
他的心臟因为摄入过量咖啡因和阿德拉而狂乱地跳动著,仿佛隨时会撞破胸膛跳出来。手指因为长时间保持高强度的敲击而开始抽筋。房间里瀰漫著一股浓烈的汗臭味、咖啡餿味和久未洗澡的酸腐味。
但他没有停,不能停,停下就是死。
这种把脑力压榨到极限的痛苦,比在街头被几个大汉围殴还要噁心百倍。肉体的疼痛熬一熬就过去了,但这种精神上的紧绷,与透支生命无异。
屏幕右下角的时间在一分一秒地流逝。
周三的太阳升起,照在利普那张形如枯槁的脸上。他双眼布满血丝,眼眶深陷,眼底掛著两个可怕的黑眼圈。他就像一台即將报废的机器,全靠著最后一丝求生欲的执念在运转。
“滑动判定……完成。”
“动画过渡帧……完成。”
“重新开始的內存释放……完成。”
下午四点五十分。距离杨坚定下的48小时死线,只剩下最后十分钟。
“啪!”
利普重重地敲下了最后一个回车键。编译,打包,生成。
看著屏幕上显示出“build successful”(构建成功)的绿色字体,利普那根紧绷了整整两天两夜的神经,终於发出一声不堪重负的脆响。
他颤抖著拔下插在电脑上的u盘,抓起一件充满异味的夹克披在身上,跌跌撞撞地拉开房门,犹如一个从坟墓里爬出来的殭尸,朝著门外衝去。
……
周三下午五点整。
“砰砰砰!”
杨坚家的大门被敲响。
杨坚拉开门,一股浓烈的酸臭味扑面而来。利普顶著一头如同鸡窝般的乱发,双眼红得像兔子,嘴唇乾裂起皮,整个人仿佛瞬间老了十岁。
他虚弱地靠在门框上,声音沙哑得如同砂纸摩擦:“最后一个功能的代码已经提交了……我已经合併到主分支了。”
他咽了一口乾涩的唾沫,死死抓著门框,还想强撑著说点什么,“我想看著它……看著它上线……”
然而,话还没说完,一旦紧绷的生死弦鬆开,彻底透支的身体瞬间发出了强制关机的指令。
利普双眼一翻,双腿一软,整个人直挺挺地往前倒去。
杨坚眼疾手快地往旁边退了一步,顺势抓住了利普的后衣领,像拖死狗一样把他拖进了温暖的客厅,直接扔在那张宽大柔软的沙发上。
几乎是接触到沙发的瞬间,利普连哪怕一秒钟的挣扎都没有,直接陷入了深度昏迷般的睡眠中,震天响的呼嚕声立刻在客厅里迴荡起来。
看著沙发上那个满身酸臭味、几乎拼了半条命的南区天才,杨坚嘴角微微上扬,露出一抹满意的弧度。
温室里的花朵是经不起风浪的,只有经过这种地狱般压榨的打磨,一块生铁才能真正淬火成钢。
“做得不错。接下来,轮到我了。”
杨坚转身走向吧檯,隨意拿起半块已经发硬的全麦麵包咬在嘴里,给自己冲了一杯高浓度的黑咖啡。隨后,他坐到了那台配置顶级的笔记本电脑前。
杨坚熟练地打开终端命令行,把代码从远程管理仓库拉取到本地。
看著屏幕上飞速滚动的代码拉取日誌,他在开发环境中迅速搭建好测试框架。他没有丝毫的怜悯,直接套用了最严苛的工业级標准来验收这个由南区少年花48小时爆肝赶出来的奇蹟。
虽然杨坚前世主攻的是底层云计算和架构设计,对於java这种应用层面的语言细节了解得並不算极度深透,但这根本不是问题。因为对於一个资深程式设计师来说,语言只是工具,真正核心的,是他脑海里那套滚瓜烂熟、经过无数硅谷大厂验证过的现代软体工程测试范式。
首先是单元测试(unit tests)。
杨坚飞快地阅读著测试脚本,验证核心逻辑。数字2和2滑动是否一定会合成4?网格数组在移动时是否会发生越界崩溃?隨机生成新数字的概率是否完全符合预期?
一行行绿色的pass闪过。基础逻辑竟然出奇的扎实。
“这小子的確是个天才,在脑子糊涂成那样的情况下,核心算法居然没出错。”杨坚暗自讚赏了一句。
但接下来的测试,才是真正的折磨。
冒烟测试(smoke test)与集成测试(integration tests)。
杨坚將代码编译到安卓模擬器上,开始进行ui与逻辑的对接测试。他模擬极其狂暴的乱点操作,在方块合併动画还没有播放完毕时,强行进行反方向的滑动。
“咔。”
模擬器画面瞬间定格,后台终端弹出一长串刺眼的红色报错信息:nullpointerexception(空指针异常)。
动画队列出现了死锁,导致下一次滑动的状態读取失败。
遇到这种问题,一般的宽容老板可能会自己顺手改了。但杨坚的行事风格显然不是这样。
他站起身,走到沙发旁,面无表情地伸出穿著拖鞋的脚,对著利普的大腿狠狠地踹了一脚。
“起来!”
利普在睡梦中发出一声痛苦的闷哼,像触电般惊醒过来,眼神迷离地看著天花板,大脑完全处於宕机状態:“啊……怎么了?马库斯打进来了?”
“没打进来,但你的代码崩溃了。”杨坚一把揪住他的衣领,將他从沙发上硬生生拖起来,按在电脑桌前,指著屏幕上的红色报错代码,“在连续快速滑动並打断动画时,你的状態机没有做加锁处理,拋出了空指针异常。现在,立刻把它修復。”
利普痛苦地揉著脸,眼睛都睁不开,只能凭著肌肉记忆和对代码的熟悉,双手放在键盘上,像梦游一样输入了几行修復代码,加入了状態锁。
“改完了……”利普嘟囔了一句,刚想站起来,双腿一软,再次倒在沙发上,三秒钟后,呼嚕声再次响起。
杨坚冷酷地端起咖啡喝了一口,继续测试。
他又进行了端到端测试(end-to-end tests)的標准,把自己想像成一个完全不懂规则、脾气暴躁、试图用各种极端操作搞垮游戏的愚蠢玩家。
他测试了屏幕疯狂旋转时的解析度適配;测试了游戏进行到一半突然接听电话后的后台掛起与恢復机制;甚至测试了当网格全部填满且无法滑动时,游戏判定“game over”弹窗的延迟时间。
在这个过程中,只要发现任何一处內存泄漏、ui重叠或者逻辑卡死,杨坚就会毫不留情地走过去,粗暴地摇晃沙发的靠背,把睡得像死猪一样的利普再次摇醒。
“游戏重启时缓存没有彻底释放,导致內存占用堆积,改掉!”
“game over的遮罩层透传了点击事件,导致死局还能继续触发音效,改掉!”
整整四个小时。利普在这如同酷刑般的折磨中被摇醒了四次。每一次他都是闭著眼睛修改,改完又立刻昏睡过去。他甚至觉得这种折磨比马库斯的拳头还要恐怖,至少马库斯打人不会要求你解释空指针异常。
晚上九点。
当杨坚最后一次在模擬器里极其流畅地將数字拼到2048,並且故意死局,游戏完美弹出结束画面,內存释放曲线平稳时。
他终於停下了敲击键盘的手。
代码彻底乾净了。一款足够在全球掀起风暴的神级成癮小游戏,在这个芝加哥南区破败房屋里,正式诞生。
接下来,就是上线部署。
对於首发平台的选择,杨坚有著绝对清晰的时代洞察力。在这个时间节点,如果选择苹果的app store,那繁琐严苛的审核机制动輒需要一周甚至半个月的时间。等游戏上架,利普的手指早就被黑帮掰成粉末了,弗兰克欠的债也足以让加拉格一家家破人亡。
所以,杨坚毫不犹豫地选择了当时狂野如蛮荒时代的安卓平台——早期的android market(google play的前身)。
当时的安卓生態极度开放,甚至可以说是缺乏监管。审核机制简陋到了令人髮指的地步,基本上只要包名不衝突,机器稍微扫描一下確认没有恶意的木马病毒,就直接放行上架。这为杨坚抢时间提供了绝佳的土壤。
杨坚飞快地打开命令行,熟练地生成了数字签名证书。
隨后,他將那份经过地狱测试的代码进行编译打包,生成了最终版本的apk文件。
登陆开发者后台,上传apk,填写简单的英文描述:“极其简单的数字合併游戏。你能拼出2048吗?”截图也是隨便截了几张极其朴素的游玩画面。
为了確保万无一失,杨坚甚至花了几十美金,走了一个当年平台默认的“开发者加速通道”服务。
点击提交。审核开始。
在这个充斥著低劣游戏和简陋应用的市场里,《2048》那套乾净利落的代码和微小的安装包体积,在机器审核眼中简直是完美的存在。
仅仅过了一个半小时。晚上十点半。
杨坚的邮箱里弹出了清脆的提示音。
【google play developer support: your app 2048 has been successfully published and is now live.】(你的应用『2048』已成功发布並上线。)
杨坚看著那个简单的数字图標在网页上亮起,长长地吐出了一口浊气。他端起桌上那杯已经彻底冰冷的白开水,走到沙发前。
“哗啦!”
半杯冷水毫不留情地泼在了利普的脸上。
“啊!我改!我这就改异常拋出!”利普发出一声惊恐的怪叫,像触电的青蛙一样从沙发上弹了起来,双手在空中胡乱地抓著,仿佛还在敲键盘。
“不用改了。”杨坚隨手將水杯放在桌子上,指了指发光的电脑屏幕。
利普愣住了。他用袖子胡乱抹了一把脸上的冷水,强撑著睁开布满血丝的双眼,顺著杨坚手指的方向看去。
在一个简陋的应用商店网页上。一个由灰色底板和带有数字“2048”的黄色方块组成的极简图標,正安静地躺在最新上架的列表里。旁边,赫然写著它的名字——2048。
“上……上线了?”利普愣愣地看著屏幕,声音带著极度乾涩的沙哑。
整整两天两夜的地狱衝刺,让他现在的脑子还有些发懵。看著那个简陋的网页,他甚至產生了一种强烈的不真实感——就像是一场快要把他绞碎的噩梦,突然就这么结束了。
“不仅上线了,我已经掛上了谷歌的基础gg联盟代码。只要有人下载游玩,每一次底部的gg展示,都会变成真金白银流进帐户。”
杨坚语气平淡地解说著。
隨后,他拉开抽屉,拿出了之前倒卖破解手机赚来的现金,点好后將一小叠钞票扔在了利普的大腿上。
“那是整整一千美金。八百美金,是你交付项目的尾款。多出来的两百,是你这两天保质保量、熬夜赶工的加班费。”
钱並不重,只有薄薄的一小叠。但粗糙的纸幣质感和那股带著油墨味的真实感,瞬间击穿了利普的心理防线。
比起那个还没產生任何收益的乾瘪网页,大腿上这实打实的一千块现金,才是將他从断手地狱里彻底拉出来的救命稻草。
就在几天前,他还在为几百块的代考费沾沾自喜,还在为了马库斯的威胁痛哭流涕,还在因为杨坚冷酷的拒绝而感到无尽的绝望。
而现在,仅仅四十八个小时。靠著敲击键盘,靠著被压榨大脑,他竟然堂堂正正、没有偷窃、没有欺骗地赚到了整整一千块的巨款!
这是一种对旧有三观的彻底粉碎与重塑。南区那套坑蒙拐骗的街头智慧,在真正的技术变现和资本运作面前,被碾压得连渣都不剩。
“钱到手了。”杨坚转身走回电脑前,只留给利普一个背影,语气恢復了冰冷,“现在,带著你拼了半条命赚来的钱,滚回加拉格家。去把那个叫马库斯的大猩猩的窟窿给补上,保住你那双还能敲键盘的手。”
利普紧紧攥著那叠钱,指关节因为用力而微微发白。
他没有了平时那种油腔滑调的嘴硬,也没有了南区混混的桀驁不驯。他站在原地,眼眶发红,对著杨坚挺拔的背影,重重地点了点头。
“谢谢……老板。”
这句“老板”,他喊得心甘情愿,內心充满了前所未有的震撼与狂热的死心塌地。他转身推开门,冲入冰冷的黑夜中,脚步前所未有的坚定。
而此时,电脑屏幕上,“2048”的后台下载量,依然还是一个极其可怜的数字:0。一场真正的风暴,才刚刚开始酝酿。
没有了这800美金的尾款,马库斯的棒球棍將在周末无情地砸碎他的双手,而东欧黑帮则会把他的弟弟妹妹切成零件卖到黑市。
绝望,一种真正令人窒息的绝望,如附骨之疽般爬满了他全身。他甚至想过要不要去抢劫街角的便利店,或者去偷弗兰克的藏身处,但那些念头在脑海中闪过的瞬间就被他自己否定了。
钱不够,也来不及。
就在利普深一脚浅一脚地踩在满是积水的柏油马路上,准备迎接死亡的审判时。
“咔噠。”
身后,杨坚家那扇沉重的大门突然再次被人推开。一道暖黄色的灯光像利剑一样劈开了漆黑的街道,正好照在利普单薄的背影上。
利普浑身一震,猛地回过头。
杨坚依旧穿著那件单薄的短袖,双手抱在胸前,居高临下地站在门廊的台阶上。夜风吹动他额前的碎发,那双深邃的黑眸里没有任何怜悯,只有属於理智的绝对冷酷。
“啪嗒。”
一个沉甸甸的黑色塑胶袋被杨坚隨手扔了出来,精准地砸在利普脚边的水坑旁。
利普愣住了,他如同抓住救命稻草般死死盯著那个袋子,却不敢轻举妄动。
“我刚才说过了,我不做廉价的慈善,更不会无缘无故替你擦屁股。”杨坚的声音穿透冷风,清晰地砸进利普的耳朵里,“但我是一个生意人,我愿意给你一个证明自己价值,顺便完成自救的交易。”
利普猛地抬头,他几乎是连滚带爬地扑回台阶前,死死盯著杨坚:“什么交易?只要能拿到钱,我什么都干!”
杨坚指了指地上的袋子,语气毫无波澜:“你的游戏代码,距离完整交付还差整整一个星期的工作量。现在,捡起那个袋子。里面有两瓶足够让你心臟狂跳的阿德拉(adderall)提神药片,还有五罐能苦到让你舌头髮麻的黑咖啡。”
利普低头看了一眼那个袋子,脸上神色带有疑惑,显然还没反应过来。
“利普,你看过《社交网络》这部电影吗?”杨坚突然拋出了一个看似毫不相干的问题。
利普愣了一下,呆呆地点了点头。那部讲述facebook创始人发家史的电影前不久刚上映,他在电影院里偷偷溜进去看过。
“很好。”杨坚嘴角勾起一抹冰冷的弧度,“既然看过,那你就应该知道,那些改变世界的极客,在面临生死存亡的节点时是怎么做的。”
杨坚微微前倾身体,压迫感如泰山压顶般袭来:“我要你像马克·扎克伯格一样!把你那可笑的自尊心扔进垃圾桶,把自己死死锁在房间里!磕著药,喝著烂咖啡,两耳不闻窗外事,熬夜拼命把这个项目给我敲出来!”
“从现在起,我只给你四十八个小时!”
杨坚抬起手腕,看了一眼錶盘,声音如同死神的倒计时:“今天是周一晚上五点。周三下午五点之前,把剩下一周的活全部给我完美干完!如果没有致命bug,代码能顺利跑通,我就会把游戏打包上线。只要游戏上线,我就立刻结清你的尾款。”
他俯视著这个因为恐惧和激动而浑身发抖的南区天才:“如果你能在48小时內把现在的半成品变成完整版,你的手就保住了。如果干不完,或者你交给我的是一坨满是bug的屎……”
杨坚顿了顿,眼神变得无比森寒:“我就坐在这里,喝著热咖啡,透过窗户亲眼看著那帮大猩猩把你的手指一根、一根地掰断。”
“砰!”
大门再次重重关上,將所有的温暖与灯光重新隔绝。
但这一次,站在冷风中的利普没有再感到绝望。他猛地扑向地上的黑色塑胶袋,像护著稀世珍宝一样將里面的药片和咖啡死死抱在怀里。
那是他的命!那是他双手和家人的命!
利普深吸了一口冰冷的空气,原本因为恐惧而涣散的眼神,此刻爆发出一种如同饿狼般的凶狠光芒。他转身,迈开双腿,像疯了一样朝著加拉格家那栋破旧的房子狂奔而去。
……
“砰!”
利普一脚踹开自己臥室的房门,反手將其死死反锁。
隔壁房间里,菲奥娜还在因为俄罗斯黑帮的恐嚇而无助地哭泣,黛比和卡尔在楼下因为抢夺最后半块发硬的麵包而大声爭吵。整个加拉格家依然笼罩在一片混乱与末日般的压抑中。
但这一切,此刻都被利普彻底屏蔽了。
他一把扫开书桌上那些乱七八糟的杂物,將那台破旧的二手笔记本电脑小心翼翼地放在桌面上。按下开机键,屏幕亮起微弱的萤光,照亮了他那张因为极度紧张而微微抽搐的脸。
他撕开塑胶袋,拧开一瓶阿德拉,倒出两片白色的药丸,连水都没喝,直接仰起头生咽了下去。接著,他拉开一罐黑咖啡,“吨吨吨”地灌了半罐。
苦涩的液体顺著食道流下,伴隨著药效的发作,他的心臟开始加速跳动,大脑仿佛被注入了高压电流,瞬间从疲惫中清醒过来,精神亢奋到了极点。
“四十八小时……一个星期的工作量……我能做到,我他妈是个天才,我他妈一定能做到!”
利普神经质般地喃喃自语著,双手如同抽筋般猛地放在键盘上。
“啪嗒啪嗒啪嗒——”
键盘的敲击声如同暴雨般在狭小冰冷的臥室里炸响。
这是利普人生中第一次,真正意义上体验到了科技网际网路圈子里臭名昭著、折磨人的词汇——项目衝刺。
没有了平日里那种写两行代码就去抽根烟、喝口酒的散漫。
在生死存亡的倒计时面前,他彻底拋弃了所有的南区小聪明,他不再去想怎么偷车,不再去想怎么代考,他现在的世界里,只有屏幕上那些跳动的字符、模块、对象和逻辑判断。
周一的深夜,冷风顺著窗户的缝隙呼啸著灌进房间,冻得他双手发僵。他只能每隔半小时就把手放在大腿下捂热,然后再继续疯狂敲击。
ui界面的渲染、滑动逻辑的边界判定、分数翻倍的算法优化、存储最高分的本地缓存……那些原本需要大量时间去构思和调试的底层逻辑,在他的大脑超负荷运转下,被强行压缩成一行行密集的代码。
到了周二的中午,药效开始减退。一种仿佛要將灵魂撕裂的疲惫感如潮水般涌来。利普的眼皮像灌了铅一样沉重,眼前屏幕上的代码开始出现重影,字母仿佛变成了乱爬的蚂蚁。
“利普!你在里面干什么?出来吃点东西!”门外传来菲奥娜带著哭腔的敲门声,“马库斯刚才又打电话来威胁了,我们该怎么办啊……”
“別管我!別打扰我!”
利普发出野兽般的低吼。他用发抖的手再次拧开药瓶,倒出药片塞进嘴里,用冰冷的黑咖啡冲服下去。
周二的夜晚,是最难熬的地狱。
他的心臟因为摄入过量咖啡因和阿德拉而狂乱地跳动著,仿佛隨时会撞破胸膛跳出来。手指因为长时间保持高强度的敲击而开始抽筋。房间里瀰漫著一股浓烈的汗臭味、咖啡餿味和久未洗澡的酸腐味。
但他没有停,不能停,停下就是死。
这种把脑力压榨到极限的痛苦,比在街头被几个大汉围殴还要噁心百倍。肉体的疼痛熬一熬就过去了,但这种精神上的紧绷,与透支生命无异。
屏幕右下角的时间在一分一秒地流逝。
周三的太阳升起,照在利普那张形如枯槁的脸上。他双眼布满血丝,眼眶深陷,眼底掛著两个可怕的黑眼圈。他就像一台即將报废的机器,全靠著最后一丝求生欲的执念在运转。
“滑动判定……完成。”
“动画过渡帧……完成。”
“重新开始的內存释放……完成。”
下午四点五十分。距离杨坚定下的48小时死线,只剩下最后十分钟。
“啪!”
利普重重地敲下了最后一个回车键。编译,打包,生成。
看著屏幕上显示出“build successful”(构建成功)的绿色字体,利普那根紧绷了整整两天两夜的神经,终於发出一声不堪重负的脆响。
他颤抖著拔下插在电脑上的u盘,抓起一件充满异味的夹克披在身上,跌跌撞撞地拉开房门,犹如一个从坟墓里爬出来的殭尸,朝著门外衝去。
……
周三下午五点整。
“砰砰砰!”
杨坚家的大门被敲响。
杨坚拉开门,一股浓烈的酸臭味扑面而来。利普顶著一头如同鸡窝般的乱发,双眼红得像兔子,嘴唇乾裂起皮,整个人仿佛瞬间老了十岁。
他虚弱地靠在门框上,声音沙哑得如同砂纸摩擦:“最后一个功能的代码已经提交了……我已经合併到主分支了。”
他咽了一口乾涩的唾沫,死死抓著门框,还想强撑著说点什么,“我想看著它……看著它上线……”
然而,话还没说完,一旦紧绷的生死弦鬆开,彻底透支的身体瞬间发出了强制关机的指令。
利普双眼一翻,双腿一软,整个人直挺挺地往前倒去。
杨坚眼疾手快地往旁边退了一步,顺势抓住了利普的后衣领,像拖死狗一样把他拖进了温暖的客厅,直接扔在那张宽大柔软的沙发上。
几乎是接触到沙发的瞬间,利普连哪怕一秒钟的挣扎都没有,直接陷入了深度昏迷般的睡眠中,震天响的呼嚕声立刻在客厅里迴荡起来。
看著沙发上那个满身酸臭味、几乎拼了半条命的南区天才,杨坚嘴角微微上扬,露出一抹满意的弧度。
温室里的花朵是经不起风浪的,只有经过这种地狱般压榨的打磨,一块生铁才能真正淬火成钢。
“做得不错。接下来,轮到我了。”
杨坚转身走向吧檯,隨意拿起半块已经发硬的全麦麵包咬在嘴里,给自己冲了一杯高浓度的黑咖啡。隨后,他坐到了那台配置顶级的笔记本电脑前。
杨坚熟练地打开终端命令行,把代码从远程管理仓库拉取到本地。
看著屏幕上飞速滚动的代码拉取日誌,他在开发环境中迅速搭建好测试框架。他没有丝毫的怜悯,直接套用了最严苛的工业级標准来验收这个由南区少年花48小时爆肝赶出来的奇蹟。
虽然杨坚前世主攻的是底层云计算和架构设计,对於java这种应用层面的语言细节了解得並不算极度深透,但这根本不是问题。因为对於一个资深程式设计师来说,语言只是工具,真正核心的,是他脑海里那套滚瓜烂熟、经过无数硅谷大厂验证过的现代软体工程测试范式。
首先是单元测试(unit tests)。
杨坚飞快地阅读著测试脚本,验证核心逻辑。数字2和2滑动是否一定会合成4?网格数组在移动时是否会发生越界崩溃?隨机生成新数字的概率是否完全符合预期?
一行行绿色的pass闪过。基础逻辑竟然出奇的扎实。
“这小子的確是个天才,在脑子糊涂成那样的情况下,核心算法居然没出错。”杨坚暗自讚赏了一句。
但接下来的测试,才是真正的折磨。
冒烟测试(smoke test)与集成测试(integration tests)。
杨坚將代码编译到安卓模擬器上,开始进行ui与逻辑的对接测试。他模擬极其狂暴的乱点操作,在方块合併动画还没有播放完毕时,强行进行反方向的滑动。
“咔。”
模擬器画面瞬间定格,后台终端弹出一长串刺眼的红色报错信息:nullpointerexception(空指针异常)。
动画队列出现了死锁,导致下一次滑动的状態读取失败。
遇到这种问题,一般的宽容老板可能会自己顺手改了。但杨坚的行事风格显然不是这样。
他站起身,走到沙发旁,面无表情地伸出穿著拖鞋的脚,对著利普的大腿狠狠地踹了一脚。
“起来!”
利普在睡梦中发出一声痛苦的闷哼,像触电般惊醒过来,眼神迷离地看著天花板,大脑完全处於宕机状態:“啊……怎么了?马库斯打进来了?”
“没打进来,但你的代码崩溃了。”杨坚一把揪住他的衣领,將他从沙发上硬生生拖起来,按在电脑桌前,指著屏幕上的红色报错代码,“在连续快速滑动並打断动画时,你的状態机没有做加锁处理,拋出了空指针异常。现在,立刻把它修復。”
利普痛苦地揉著脸,眼睛都睁不开,只能凭著肌肉记忆和对代码的熟悉,双手放在键盘上,像梦游一样输入了几行修復代码,加入了状態锁。
“改完了……”利普嘟囔了一句,刚想站起来,双腿一软,再次倒在沙发上,三秒钟后,呼嚕声再次响起。
杨坚冷酷地端起咖啡喝了一口,继续测试。
他又进行了端到端测试(end-to-end tests)的標准,把自己想像成一个完全不懂规则、脾气暴躁、试图用各种极端操作搞垮游戏的愚蠢玩家。
他测试了屏幕疯狂旋转时的解析度適配;测试了游戏进行到一半突然接听电话后的后台掛起与恢復机制;甚至测试了当网格全部填满且无法滑动时,游戏判定“game over”弹窗的延迟时间。
在这个过程中,只要发现任何一处內存泄漏、ui重叠或者逻辑卡死,杨坚就会毫不留情地走过去,粗暴地摇晃沙发的靠背,把睡得像死猪一样的利普再次摇醒。
“游戏重启时缓存没有彻底释放,导致內存占用堆积,改掉!”
“game over的遮罩层透传了点击事件,导致死局还能继续触发音效,改掉!”
整整四个小时。利普在这如同酷刑般的折磨中被摇醒了四次。每一次他都是闭著眼睛修改,改完又立刻昏睡过去。他甚至觉得这种折磨比马库斯的拳头还要恐怖,至少马库斯打人不会要求你解释空指针异常。
晚上九点。
当杨坚最后一次在模擬器里极其流畅地將数字拼到2048,並且故意死局,游戏完美弹出结束画面,內存释放曲线平稳时。
他终於停下了敲击键盘的手。
代码彻底乾净了。一款足够在全球掀起风暴的神级成癮小游戏,在这个芝加哥南区破败房屋里,正式诞生。
接下来,就是上线部署。
对於首发平台的选择,杨坚有著绝对清晰的时代洞察力。在这个时间节点,如果选择苹果的app store,那繁琐严苛的审核机制动輒需要一周甚至半个月的时间。等游戏上架,利普的手指早就被黑帮掰成粉末了,弗兰克欠的债也足以让加拉格一家家破人亡。
所以,杨坚毫不犹豫地选择了当时狂野如蛮荒时代的安卓平台——早期的android market(google play的前身)。
当时的安卓生態极度开放,甚至可以说是缺乏监管。审核机制简陋到了令人髮指的地步,基本上只要包名不衝突,机器稍微扫描一下確认没有恶意的木马病毒,就直接放行上架。这为杨坚抢时间提供了绝佳的土壤。
杨坚飞快地打开命令行,熟练地生成了数字签名证书。
隨后,他將那份经过地狱测试的代码进行编译打包,生成了最终版本的apk文件。
登陆开发者后台,上传apk,填写简单的英文描述:“极其简单的数字合併游戏。你能拼出2048吗?”截图也是隨便截了几张极其朴素的游玩画面。
为了確保万无一失,杨坚甚至花了几十美金,走了一个当年平台默认的“开发者加速通道”服务。
点击提交。审核开始。
在这个充斥著低劣游戏和简陋应用的市场里,《2048》那套乾净利落的代码和微小的安装包体积,在机器审核眼中简直是完美的存在。
仅仅过了一个半小时。晚上十点半。
杨坚的邮箱里弹出了清脆的提示音。
【google play developer support: your app 2048 has been successfully published and is now live.】(你的应用『2048』已成功发布並上线。)
杨坚看著那个简单的数字图標在网页上亮起,长长地吐出了一口浊气。他端起桌上那杯已经彻底冰冷的白开水,走到沙发前。
“哗啦!”
半杯冷水毫不留情地泼在了利普的脸上。
“啊!我改!我这就改异常拋出!”利普发出一声惊恐的怪叫,像触电的青蛙一样从沙发上弹了起来,双手在空中胡乱地抓著,仿佛还在敲键盘。
“不用改了。”杨坚隨手將水杯放在桌子上,指了指发光的电脑屏幕。
利普愣住了。他用袖子胡乱抹了一把脸上的冷水,强撑著睁开布满血丝的双眼,顺著杨坚手指的方向看去。
在一个简陋的应用商店网页上。一个由灰色底板和带有数字“2048”的黄色方块组成的极简图標,正安静地躺在最新上架的列表里。旁边,赫然写著它的名字——2048。
“上……上线了?”利普愣愣地看著屏幕,声音带著极度乾涩的沙哑。
整整两天两夜的地狱衝刺,让他现在的脑子还有些发懵。看著那个简陋的网页,他甚至產生了一种强烈的不真实感——就像是一场快要把他绞碎的噩梦,突然就这么结束了。
“不仅上线了,我已经掛上了谷歌的基础gg联盟代码。只要有人下载游玩,每一次底部的gg展示,都会变成真金白银流进帐户。”
杨坚语气平淡地解说著。
隨后,他拉开抽屉,拿出了之前倒卖破解手机赚来的现金,点好后將一小叠钞票扔在了利普的大腿上。
“那是整整一千美金。八百美金,是你交付项目的尾款。多出来的两百,是你这两天保质保量、熬夜赶工的加班费。”
钱並不重,只有薄薄的一小叠。但粗糙的纸幣质感和那股带著油墨味的真实感,瞬间击穿了利普的心理防线。
比起那个还没產生任何收益的乾瘪网页,大腿上这实打实的一千块现金,才是將他从断手地狱里彻底拉出来的救命稻草。
就在几天前,他还在为几百块的代考费沾沾自喜,还在为了马库斯的威胁痛哭流涕,还在因为杨坚冷酷的拒绝而感到无尽的绝望。
而现在,仅仅四十八个小时。靠著敲击键盘,靠著被压榨大脑,他竟然堂堂正正、没有偷窃、没有欺骗地赚到了整整一千块的巨款!
这是一种对旧有三观的彻底粉碎与重塑。南区那套坑蒙拐骗的街头智慧,在真正的技术变现和资本运作面前,被碾压得连渣都不剩。
“钱到手了。”杨坚转身走回电脑前,只留给利普一个背影,语气恢復了冰冷,“现在,带著你拼了半条命赚来的钱,滚回加拉格家。去把那个叫马库斯的大猩猩的窟窿给补上,保住你那双还能敲键盘的手。”
利普紧紧攥著那叠钱,指关节因为用力而微微发白。
他没有了平时那种油腔滑调的嘴硬,也没有了南区混混的桀驁不驯。他站在原地,眼眶发红,对著杨坚挺拔的背影,重重地点了点头。
“谢谢……老板。”
这句“老板”,他喊得心甘情愿,內心充满了前所未有的震撼与狂热的死心塌地。他转身推开门,冲入冰冷的黑夜中,脚步前所未有的坚定。
而此时,电脑屏幕上,“2048”的后台下载量,依然还是一个极其可怜的数字:0。一场真正的风暴,才刚刚开始酝酿。