原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、写一个游戏框架(一)
5、写一个游戏框架(二)
6、通过Canvas实现视差滚动
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

在Canvas元素上实现视差滚动

http://www.brighthub.com/internet/web-development/articles/40511.aspx

视差滚动是在2D应用中创造立体纵深感的一种技术。这篇文章就来看一看在我们刚刚创建的游戏框架基础上实现视差滚动有多容易。

视差滚动

有了游戏框架,就可以通过画布元素来做一些好玩的东西了。

视差滚动指的是屏幕上的几个图层发生相对位移的效果,换句话说,背景图层滚动得比它前面的那些图层要慢一些。这种创造视觉纵深感的技术在2D游戏中的应用极为普遍。

RepeatingGameObject.js


/**
    这个类可以重复显示纹理图像,支持纹理图像在x轴或y轴偏移
    @class
*/
function RepeatingGameObject()
{
    /** 最终图像占据的宽度
 	@type Number
    */
    this.width = 0;
    /** 最终图像占据的高度
    	@type Number
    */
    this.height = 0;
    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
    this.scrollFactor = 1;

    /**
        初始化对象
        @return 对初始化对象的引用
    */
    this.startupRepeatingGameObject = function(image, x, y, z, width, height, scrollFactor)
    {
        this.startupVisualGameObject(image, x, y, z);
        this.width = width;
        this.height = height;
        this.scrollFactor = scrollFactor;
        return this;
    }

    /**
        清理对象
    */
    this.shutdownstartupRepeatingGameObject = function()
    {
        this.shutdownVisualGameObject();
    }

	/**
        把当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
		@param context 绘制上下文
		@param xScroll x轴的全局滚动值
		@param yScroll y轴的全局滚动值

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y < this.height; y += areaDrawn[1])
        {
            for (var x = 0; x < this.width; x += areaDrawn[0])
            {
                // 绘制下一张贴片左上角的点
		var newPosition = [this.x + x, this.y + y];
		// 剩余的绘制空间
                var newFillArea = [this.width - x, this.height - y];
		// 第一次必须从图像的中央开始绘制
		// 后续贴片从上方或左侧绘制
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        // 找到重复绘制纹理图像的起点(左上角)
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]<0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]<0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] < this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] < this.image.height-top?newFillArea[1]:this.image.height-top;

        // 绘制图像
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }
}
RepeatingGameObject.prototype = new VisualGameObject();

这个RepeatingGameObject类可以让图像在一个确定的区域内重复和滚动。此前,我们已经实现了绘制整幅图像。而RepeatingGameObject的不同之处在于,它拿到一幅图像并用它来填充一块范围既定的区域(其尺寸与绘制的图像无关)。我们通过这个类每次显示一幅大图像(如一座山的全景图)的一小部分,从而创建出一个背景。

也许你已经注意到了GameObjectManager的xScroll和yScroll属性,它们被传递给了GameObject的draw和updata函数。这两个值定义的是摄像机沿x轴或y轴移动了多远。RepeatingGameObject使用这两个值来它们显示的纹理,以创造移动的假象。

首先,定义RepeatingGameObject要绘制的区域。底层的GameObject类的x和y属性定义了左上角位置,而新的width和height属性定义的是绘制区域。


    /** 最终图像占据的宽度
 	@type Number
    */
    this.width = 0;
    /** 最终图像占据的高度
    	@type Number
    */
    this.height = 0;
    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */

而scrollFactor属性用于改变RepeatingGameObject滚动的量,该变化是通过传递到draw函数的xScroll和yScroll来控制的。将scrollFactor设置为小于1的值,会导致滚动变慢,从而造就画面中的远景。


    /** 绘制时应用多少scrollX和scrollY
	@type Number
    */
    this.scrollFactor = 1;

最后两个draw和drawRepeat函数具体负责渲染贴片及偏移的纹理。


	/**
        把当前元素绘制到后台缓冲
        @param dt 自上一帧绘制起经过的秒数
		@param context 绘制上下文
		@param xScroll x轴的全局滚动值
		@param yScroll y轴的全局滚动值

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y < this.height; y += areaDrawn[1])
        {
            for (var x = 0; x < this.width; x += areaDrawn[0])
            {
                // 绘制下一张贴片左上角的点
		var newPosition = [this.x + x, this.y + y];
		// 剩余的绘制空间
                var newFillArea = [this.width - x, this.height - y];
		// 第一次必须从图像的中央开始绘制
		// 后续贴片从上方或左侧绘制
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        // 找到重复绘制纹理图像的起点(左上角)
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]<0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]<0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] < this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] < this.image.height-top?newFillArea[1]:this.image.height-top;

        // 绘制图像
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }   

ApplicationManager.js


/**
    ApplicationManager用于管理应用
    @class
*/
function ApplicationManager()
{
    /**
        初始化对象
        @return A 对初始化对象的引用
    */
    this.startupApplicationManager = function()
    {
        this.startupGameObject();
	this.background3 = new RepeatingGameObject().startupRepeatingGameObject(g_back2, 0, 100, 3, 600, 320, 1);
        this.background2 = new RepeatingGameObject().startupRepeatingGameObject(g_back1, 0, 100, 2, 600, 320, 0.75);
        this.background = new RepeatingGameObject().startupRepeatingGameObject(g_back0, 0, 0, 1, 600, 320, 0.5);
        return this;
    }

	/**
        更新当前对象
        @param dt 自上一帧绘制起经过的秒数
        @param context 绘制上下文
        @param xScroll x轴的全局滚动值
        @param yScroll y轴的全局滚动值
    */
    this.update = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
		g_GameObjectManager.xScroll += 50 * dt;
	}
}
ApplicationManager.prototype = new GameObject

在这里,我们通过ApplicationManager创建了三个RepeatingGameObject类的实例,每个实例分别显示为一个图层,使用z(深度)和scrollFactor值来创造RepeatingGameObject 渐远和渐慢的效果。

最终结果很不错。视差滚动为画布赋予了完美的纵深感,而整个效果只多编写了一个类就实现了。

看一看视差滚动的Demo吧。http://webdemos.sourceforge.net/jsplatformer4/jsplatformer4.html

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、写一个游戏框架(一)
5、写一个游戏框架(二)
6、通过Canvas实现视差滚动
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

4、写一个游戏框架(二)

在这篇文章里,我们继续介绍构成这个基本JavaScript游戏框架的其他必要的类。

前一篇文章介绍了GameObjectManager类,该类负责画布的渲染并允许GameObject类更新和删除它们自己。下面就来看一看GameObject类。

GameObject.js


/**
    游戏中出现的所有元素的基类
    @class
*/
function GameObject()
{
    /** 显示的深度次序。较小的zOrder值表示先渲染,因而会在背景中。
        @type Number
    */
    this.zOrder = 0;
    /**
        x轴的坐标
        @type Number
    */
    this.x = 0;
    /**
        y轴的坐标
        @type Number
    */
    this.y = 0;

    /**
        初始化游戏对象,并将其添加到GameObjectManager维护的对象列表中
        @param x        x轴的坐标
        @param y        y轴的坐标
        @param z        元素的z次序(背景元素的z值较小)
    */
    this.startupGameObject = function(/**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.zOrder = z;
        this.x = x;
        this.y = y;
        g_GameObjectManager.addGameObject(this);
        return this;
    }

    /**
        清理当前对象,将其从GameObjectManager维护的对象列表中删除
    */
    this.shutdownGameObject = function()
    {
        g_GameObjectManager.removeGameObject(this);
    }
}

这个GameObject类(是一个引擎类)的目的,是为游戏中将会出现的所有对象定义一些共有的属性,包括它们的位置(x和y)和深度(z)。需要注意的是,我们不会直接创建GameObject类的实例,而是会再创建一个类来扩展它。

这个类的x和y坐标值没有什么好说的——就是相应对象左上角位置在画布上的坐标。关键是GameObject中的z值,这个值定义的是对象的深度。理解这个值很重要,这个值较小的GameObject会先绘制到画布上。换句话说,z值较大的GameObject将被绘制到z值较小的GameObject上面。
查看全文 »

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、写一个游戏框架(一)
5、写一个游戏框架(二)
6、通过Canvas实现视差滚动
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

4、写一个游戏框架(一)

http://www.brighthub.com/internet/web-development/articles/40512.aspx
在知道了如何使用画布元素之后,接下来我教大家写一个框架,有了这个框架,我们就可以把它作为基础来创建游戏。在这第一部分,我们会介绍前两个文件/类。

编写代码之前,我们先来看一看随后几篇文章将致力于创建的示例Demo。表面上看起来,这个Demo跟第二篇文章里的那个没啥区别,但如果你看看后台(查看网页源代码)就会发现,为了更方便地创建这个最终效果,一个凝聚不少心血的基础框架已经写好了。

下面我们要介绍的JavaScript代码使用面向对象的方式来编写。对于没有编写过多少JavaScript代码的人来说,恐怕第一眼看到它们会觉得有点奇怪。如果你真的不太熟悉JavaScript的面向对象编程,建议通过Mozilla Developer Network的这个教程https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript来补补课。这篇教程里解释了我们稍后会用到的一些编程技术。

从设计思想上来看,这个框架可以分成两部分:与底层的2D引擎交互的类(用于操作画布、控制渲染循环、处理输入等的代码)和用来创建对象以便构成游戏的类。前者可以归为引擎类,后者可以归为应用类。由于应用类要构建于引擎类之上,所以我们需要先来创建引擎类。
查看全文 »

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、通过Canvas实现视差滚动
5、写一个游戏框架(一)
6、写一个游戏框架(二)
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

3、通过Canvas元素实现高级图像操作

http://www.brighthub.com/internet/web-development/articles/39509.aspx

这篇文章将带领大家学习使用JavaScript和Canvas元素操作图像了几种不同的方式,这些方式在Canvas元素出现之前是不可能的事儿。

上一篇文章演示了如何利用Canvas实现一个基本的图像动画。那个例子很简单,同样的效果通过修改IMG或DIV等标准HTML元素的一些属性,照样也可以轻易实现。下面我们就来演示一下画布元素的高级应用,展示一下它的真正威力。

首先,还是准备一个HTML页面。


  < !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
  <html lang="en">
     <head>
        <title>JavaScript Platformer 2</title>
        <script type="text/javascript" src="jsplatformer2.js"></script>
        <style type="text/css">
           body { font-family: Arial,Helvetica,sans-serif;}
        </style>
     </head>
    <body>
       <p>
          <a href="http://www.brighthub.com/internet/web-development/articles/38364.aspx">
             Game Development with Javascript and the canvas element
          </a>
       </p>
       <canvas id="canvas" width="600" height="400">
          <p>Your browser does not support the canvas element.</p>
       </canvas>
       <br />
       <button onclick="currentFunction=alpha;">Change Alpha</button>
       <button onclick="currentFunction=shear;">Shear</button>
       <button onclick="currentFunction=scale;">Scale</button>
       <button onclick="currentFunction=rotate;">Rotate</button>
    </body>
 </html>

与上个一例子的HTML页面相比,唯一的区别就是添加了一些按钮。单击这些按钮,就会设置currentFunction变量(稍后介绍)的值,用以改变在渲染循环中运行的函数。
查看全文 »

原文作者:Matthew Casperson • 编辑:Michele McDonough
原文链接: Game Development with JavaScript and the Canvas element

1、认识一下Canvas
2、在Canvas上绘图
3、通过Canvas元素实现高级图像操作
4、通过Canvas实现视差滚动
5、写一个游戏框架(一)
6、写一个游戏框架(二)
7、动画
8、JavaScript键盘输入
9、综合运用
10、定义级别
11、跳跃与坠落
12、添加道具
13、加载资源
14、添加主菜单

1、认识一下Canvas

http://www.brighthub.com/internet/web-development/articles/38364.aspx

Canvas元素以及JavaScript引擎中新增的一些特性,让Web开发人员不必借助第三方插件,即可设计开发出精细且具有交互性的2D网页。这篇文章就向大家介绍一下Canvas元素,以及它的一些可能的用途。

JavaScript与Canvas元素

HTML是为创建静态页面而生的。HTML所能实现的动态效果,也仅限于显示GIF动画和闪烁的文本。JavaScript改变了这一切,通过它能够动态修改网页。今天,很多Web服务都利用AJAX来创建网页,为用户提供更加流畅的体验,也超越了标准HTML页面中常见的“点击-重新加载-点击”式的交互模式。

然而,JavaScript的某些功能会受到其宿主浏览器的制约。尽管可以在网页中创建和修改任何元素,但JavaScript不能(轻易地)让浏览器显示一种新对象。通过JavaScript修改文本、插入图像或者缩放表格都很容易,因为这些对象本来就是HTML所支持的。如果你想再玩得刺激一点,比如写一个网页游戏,怎么办?那恐怕就得苦心积虑地改变标准HTML元素的用途,克服种种不测才能达到目的。要么,你就得求助于Flash或Silverlight这样的插件。

Canvas元素登场了。这个新HTML元素为JavaScript开发者提供了一种无需插件即可在网页中直接绘图的机制。Canvas元素最早是由苹果公司在其WebKit框架中引入的,Safari浏览器和Dashboard微件都在使用。Canvas元素现在也被建议加入了HTML5规范,得到了最新的Chrome、Firefox、Opera以及Konqueror等浏览器的支持。Internet Explorer(至少在IE8之前)还不支持Canvas,但ExplorerCanvas项目倒是为IE提供了与Canvas元素类似的功能。

Canvas元素对做过2D图形编程的人是小菜一碟。可以在这个元素上画线、画各种形状、画渐变,甚至可以利用与其他2D API中类似的函数来修改其中的每一个像素。得益于Chrome的V8、Firefox的SpiderMonkey以及Safari的Nitro等最新JavaScript引擎的性能,创建精细且具有交互性的Web应用已经完全没有问题。

我们这一系列文章将教会大家使用JavaScript和Canvas元素创建一个简单的平台游戏。将要涉及的内容包括动画、加载资源、分层渲染、滚动和交互。通过一步一步地展示示例代码和实际效果,你可以很快学会如何驾驭强大的Canvas元素。

2、在Canvas上绘图

http://www.brighthub.com/internet/web-development/articles/38744.aspx

下面,我们就通过一个循序渐进的示例及实时演示,来介绍如何使用JavaScript在Canvas元素上绘图及实现动画。

准备工作

知道了什么是Canvas元素之后,该学习在屏幕上绘图了。首先,需要一个HTML页面来放置和显示Canvas元素。
查看全文 »

原文地址:JavaScript is Assembly Language for the Web: Part 2 – Madness or just Insanity?

有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此,我询问了几位JavaScript权威,比如Brendan Eich(JavaScript之父)、Douglas Crockford(JSON之父),还有Mike Shaver(Mozilla技术副总裁)。以下都是从个人邮件里摘过来的,得到了以上几位的许可。

Mike Shaver

以前我就听说过这种比较,我认为很大程度上确实如此。但是,这种说法忽视了JS开发人员与机器之间的人机工程学方面的大量努力,因为汇编语法设计得没有那么人性化(特别是现代的汇编语言)。

Brendan Eich

几年前,我曾说过“JS是Web的x86”(好像是在一次JSConf上),不过我不敢说我是第一个这么说的。(Nick Thompson今年也在Hacker News中这么说过。)

关键在于,JS确实在按照我们想的,越来越往低级方向发展了。但它也具备高级的特性。

Shaver说得没错,汇编缺少可靠的宏处理器,因此不适合程序员,也不够安全。但JS可不是这样。所以,这个比喻需要加点限制条件,不然就要闹出笑话来了。

无论从高级函数式编程还是内存安全角这个角度看,还是从低级特性,像类型化数组以及即将成为现实的ES中类型化数组的扩展、二进制数据,等等来说,JS都是一个比汇编更加强大的编程语言。当然了,内存安全是首要的区别。

查看全文 »

原文地址:JavaScript is Assembly Language for the Web: Sematic Markup is Dead! Clean vs. Machine-coded HTML

(更新)有些人认为“JavaScript是Web的汇编语言”完全是精神病说的话。为此,我询问了几位JavaScript权威,比如Brendan Eich(JavaScript之父)、Douglas Crockford(JSON之父),还有Mike Shaver(Mozilla技术副总裁)。他们的评论发表在下一篇文章里

昨天我跟Erik Meijer聊天,他说:

JavaScript就是一个汇编语言。JavaScript加上生成的HTML就像是.NET汇编一样。浏览器可以执行这些代码,但没人真的关心里面到底写的是什么。
——Erik Meijer

怎么会说起这件事儿呢?当时我正在试用Google+,就跟上大多数让我印象深刻的网站一样,我立即就查看它的源代码。不看不要紧,一看吓一跳:

咱就将就说吧,我看到了1300行代码,密密麻麻的,大约90KB。上面图片显示的只是最前面的一小部分,基本上都是“瘦身后”的JavaScript代码。再往下看,页面中间呢,全都是像下面这样的span、div以及生成的类和id: 查看全文 »

日文版:Mr Junichi Niino,Rubyの進歩がより速くなることを期待している
英文版:I am looking forward to accelerating Ruby’s progress

我在前一篇文章里已经提到过了,松本行弘(Yukihiro Matsumoto,或Matz)已经加入了Heroku,成为该公司的首席Ruby架构师。我通过电子邮件询问了Matz对自己未来的设想。

“让Ruby核心功能更丰富、品质更高是我的使命。”

PublicKey(以下称Q):能不能介绍一下你怎么就换工作了呢?

松本行弘先生(以下称Matz):上一次跟Marc Benioff先生(Salesforce.com的CEO)碰面时,他就问我,怎么才可以支持Ruby的开发。

于是,我就说了,我说我想要改变当前大多数Ruby核心开发人员面临的窘境:这些人有的是牺牲自己的闲暇时间来完成自己的工作,有的还在为自己的职业前途担心。

然后,他就说他可以为我们提供一些支持,而这也是我通过Heroku加入Salesforce.com的原因(注意:目前还有几位Ruby核心开发人员也正协商加入Heroku)。

也就是说,我们工作的核心内容没有变。我们的使命依旧还是开发Ruby核心,把它变得功能更丰富、品质更高。如此说来,我期待着我们提供的职业前景,以及来自包括Heroku在内的大量Ruby用户的反馈,能够加速Ruby开发的进程。要不然,我换这次工作就没有什么意义了。

不过,加入Heroku并担任他们的首席架构师,并不意味着我只关心Heroku和Salesforce.com的发展。我加入他们不会改变我与NaCI还有Rakuten的合作关系,后两者仍然会继续支持我,而且我还将继续担任Ruby协会的会长一职。

我为什么选这个头衔?因为我觉得“首席架构师”这个名字听起来显得最容易与业务撇清关系。我不打算将来在Heroku参与任何业务上的决策。

Q:你对自己在Heroku的角色有什么期许?

Matz:刚才不是已经说了嘛,我的工作没有什么变化,但我们的开发进度会加快。除此之外,我还能与Heroku进行更加密切的沟通,以便尽早解除Ruby对云计算平台的限制(如果有限制的话)。

而且,我还会继续与Engine Yard、VMWare等公司保持良好的关系,即使我加入了Heroku,我仍然还是那个“Ruby的Matz”,不会辜负他们的信任。

Q:此时此刻,你对Ruby和云计算有什么看法?

Matz:说实话,很多Ruby核心开发人员(包括我自己)都对Web没有多大的兴趣,但云计算会变得越来越重要,这一点是显而易见的。所以,我希望能从这些云计算运营商那里得到更多的需求,以便将其反映到未来的Ruby中。

Q:你会去硅谷上班吗,还是在松江远程工作?

Matz:我的生活方式不会变(但工作方式会变),所以多数时候我会在松江的家里远程参与开发。

就我自己而言,搬到硅谷去工作不一定会比现在这个环境更好。

不过,我想我每年都会跟旧金山/硅谷(包括Heroku)的那些人直接沟通几次。

(注意:大家别误会,Heroku的总部在旧金山,不在硅谷,但他们在新闻稿里自称是“硅谷公司”。)

Q:还有别的要说的吗?

Matz:我听说很多(日本之外国家的)人并不知道,Ruby核心团队迄今还没有一个可持续的发展模式。我希望我这次换工作能为代表日本发布消息的日本软件开发人员树立一个榜样。

Q:谢谢你接受采访。

原文地址:http://radar.oreilly.com/2011/06/time-to-learn-javascript.html
作者简介:Mike Loukides

很长时间以来,JavaScript在我眼里都是编程语言中的二等公民。早先,它经常是很多安全问题的发源地,就像是胶水一样,它能把HTML应用与样式粘到一块,可没有人拿它来正正规规地写程序;这样的情形太普遍了。而Java、Ruby、Python,这些才是真正能用来写程序的语言。

过去几年间,我对JavaScript的态度有了彻底的改变。JavaScript已经“长大成人”了。我敢保证很多JavaScript开发人员都不会认同我前面的说法,他们会说JavaScript一直都是一个十分强大、成熟、深得人心的语言。或许他们说得没错,事实上只要是一门完整的编程语言,就能拿来写程序,也包括BASIC这种滥东西。而一门语言真正有用,必须一方面自身具备很强的表达能力,另一方面还要有众多的库和开发工具。显然,JavaScript的表达能力早就没有问题了,即便是创建对象的方式有点不好让人接受,其实问题也不大。直到最近,一些极其重要的扭转局面的技术出现了:jQuery、JSON、Node.js和HTML5。或许JavaScript以前就是一门完善的语言了,但却是这些重要的相关技术(以及其他一些没有在这里提及的),让JavaScript成为了每一个开发人员都知道的语言。如果明年你要学一门新语言的话,那一定就是JavaScript。

潜力无限的Node.js

Node.js潜力无限的意思,就是它有可能引发Web开发的革命。Node.js是一个框架,用于构建高性能Web应用——即使是巨量的请求也能应对如流。虽然Node本身作为一个底层框架,能够用于构建任何应用,但它还是最适合构建Web服务器。它的异步事件驱动模式与传统的请求-响应模式相比,无疑更适合Web应用。 查看全文 »

原文地址:My startup story: from big idea to thriving business in 8 short years

2003年夏天,我还在打理自己第一个小公司的时候,突然想到一个“好主意”:社交新闻阅读器。有点类似后来的Google阅读器加智能收件箱(Priority Inbox)和社会化推荐。我没日没夜地想着这件事,觉也睡不着了。每天人虽然躺在床上,脑子里一直在苦思冥想怎么把这个东西做出来。我可能是得了“痴心妄想症”了。“这个阅读器一定会大受欢迎!”,我想。这个想法太好了,要是你的话,恐怕你早就拿着它去招徕风险投资了。可我在温莎(Windsor),加拿大呀,硅谷对我来说太远了,再说我那时候还没听说过VC啊投资啊什么的。我只能靠自己,什么事都从头来。

2003年还没有Google阅读器,Fackbook还在娘胎里,RSS新闻源也少得可怜。找不着RSS源?不要紧,我自己来,我可以自己写一个程序,一个网站一个网站地分析,自动采集新闻或者新内容。没有Faccbook提供社交用户资料?这还真是个问题。没有这些用户,还做什么社交新闻阅读器呢。对,没有用户不行,不仅如此,用户太少也不行。看来我这个“好主意”一时半会是不太可能有结果了,为了吸引用户,我决定先做个简单的东西,免费供人们下载。我对计算机通话还有些经验,开发个小桌面应用,显示来电者的ID对我来说不过举手之劳。两个月后,PhoneTray Free呱呱坠地。

2003年我可真是熬过来的。我的第一家创业公司本来还小有成就,但很快就下滑到了破产的边缘。由于我签证上的身份,我也不能给别人做任何咨询。照直说吧,这一年我没挣多少钱,我差一点就把自己的公司扔掉,然后去找一份全职工作。幸好我妻子还有工作,我们也还有点存款,合计了一下,我们决心一块挺过去,我还接着做自己想做的事。 查看全文 »