【HTML5 Canvas游戏开发】笔记(二) 显示一张图片

本系列文章由Shin-Knight编写,转载需注明出处。

作者:Shin-Knight

邮箱:shinknight@163.com

文章链接:http://www.cnblogs.com/knightls/p/3281387.html

 

在笔记一中,我们对html5游戏开发做了一个总的概述,接下来就该轮到实现功能的时候了。在上一章中也提到过,图片是游戏中不可缺少的一部分,因此我们今天就先来实现一下。

首先,我觉得可以先讲一讲本次开发的原理和设计方案:

为了方便以后实现层次化效果,我们可以采用绘画的先后顺序来实现。但是如果说我们有两个层:A和B,如下图放置:

假设我们先画了B层,然后再画了A层。接着,我们往B层上添加个C层,这时候,如果还是将C层直接画在界面上,显示是在A层上,而不是B层上,因此,我们需要不断地重画这个界面。将A层,B层,C层加到显示列表中,通过遍历这个列表进行显示。当然,这是以后涉及到层次化效果的时候要使用的,现在讲讲只是为了理解本文中,我采取重绘界面做法的意义。

由于本次开发涉及到封装,所以暂时给这个项目取名为Tomato2D吧,哈哈。 名字是随便想的,以后或许还会改。

 

一,TGlobalVar 、TMainWindow和TApplication类

有一些全局的变量和函数为了使用起来不重复,因此定义了一个TGlobalVar静态类,它负责装一些全局变量和函数,以免使用的时候和其他的变量相同。如下:

1 var TGlobalVar = function(){this.type = "TGlobalVar";};

这个以后如果有其他变量加入的话,会慢慢拓展。接下来为了使界面结构更清晰我们还要建立一个TMainWindow和TApplication类。负责全局的驱动和存储一些全局数据。

先看TMainWindow的代码:

 1 function TMainWindow(data){
 2     var self = this;
 3     
 4     self.type = "TMainWindow";
 5     
 6     self.childList = new Array();
 7     self.width = data.width || 200;
 8     self.height = data.height || 120;
 9     TGlobalVar.TApplicationObj.id = data.id;
10     TGlobalVar.TApplicationObj.frameRate = data.frameRate;
11 }
12 TMainWindow.prototype.init = function(){
13     var self = this;
14     
15     if(TGlobalVar.isAddMainWindow == true)return;
16     TGlobalVar.TMainWindowObj = self;
17     TGlobalVar.isAddMainWindow = true;
18     var w = self.width;
19     var h = self.height;
20     TGlobalVar.TApplicationObj.canvasObj = document.getElementById(TGlobalVar.TApplicationObj.id);
21     TGlobalVar.TApplicationObj.canvasObj.width = w;
22     TGlobalVar.TApplicationObj.canvasObj.height = h;
23 };
24 TMainWindow.prototype.onShow = function(){
25     var self = this;
26     if(TGlobalVar.TApplicationObj.canvas == null)return;
27     TGlobalVar.TApplicationObj.canvas.clearRect(0,0,TGlobalVar.TApplicationObj.width,TGlobalVar.TApplicationObj.height);  
28     self.show(self.childList);
29 };
30 TMainWindow.prototype.show = function(showlist,cood){
31     if(cood == null)cood={x:0,y:0};
32     var key = null;
33     for(key in showlist){
34         if(showlist[key].show){
35             showlist[key].show(cood);
36         }
37     }
38 };

这个类实例化的时候有一个参数,是一个json对象,格式如下:

1 {
2         id:canvas的id,
3         width:canvas的宽,
4         height:canvas的高,
5         frameRate:刷新频率
6 }

然后调用TMainWindow的init时,会自动保存这些数据,在其中用到了TGlobalVar.isAddMainWindow,TGlobalVar.TMainWindowObj,TGlobalVar.TApplicationObj这几个变量,其中TGlobalVar.isAddMainWindow是用来判断是否已经init过TMainWindow,因为界面上不可能有两个TMainWindow,所以用这个加以限制,而TGlobalVar.TMainWindowObj是用来保存界面上TMainWindow的变量,TGlobalVar.TApplicationObj是用来保存界面上TApplication对象的变量。

在TMainWindow类中,还有个onShow和show方法,这两个方法是用来刷新界面用的。onShow是负责清空界面和调用show方法用的。在show方法中通过遍历TMainWindow里的childList,调用遍历到的元素的show方法,实现重绘,也就是说,在childList里的元素必须有show方法才行。onShow方法在TApplication中会用到。

具体TApplication里的代码如下:

 1 function TApplication(){
 2     var self = this;
 3     self.type = "TApplication";
 4     self.canvas = null;
 5     self.canvasObj = null;
 6     self.frameRate = 50;
 7     self.objectIndex = 0;
 8     self.id = null;
 9     self.driver = null;
10     
11     TGlobalVar.TApplicationObj = self;
12 }
13 TApplication.prototype.exec = function(){
14     var self = this;
15     
16     if(TGlobalVar.isAddApplication == true)return;
17     TGlobalVar.isAddApplication = true;
18     self.canvas = self.canvasObj.getContext("2d");
19     self.driver = setInterval(function(){TGlobalVar.TMainWindowObj.onShow();},self.frameRate);
20 };

这个类应该是在TMainWindow前实例化,否则就会报错。但是在调用成员函数exec时,要在TMainWindow对象调用init之后调用。这个exec相当于是一个开启游戏重画的函数,也就是说,不调用这个函数界面将不能重画。在exec中又用到了TGlobalVar.isAddApplication这个变量,它和上文的TGlobalVar.isAddMainWindow的用途差不多,只不过一个是用来判断是否加入了TMainWindow对象,另一个是用来判断是否加入了TApplication对象。也就是说,我们使用的时候只能有一个TMainWindow对象和一个TApplication对象。用TGlobalVar.TApplicationObj和TGlobalVar.TMainWindowObj分别保存TApplication和TMainWindow对象是为了方便以后的操作。看到下面你就会明白。

因为在TGlobalVar中加了几个成员属性,因此修改TGlobalVar,完整TGlobalVar代码如下:

1 var TGlobalVar = function(){this.type = "TGlobalVar";};
2 TGlobalVar.TApplicationObj = null;
3 TGlobalVar.TMainWindowObj = null;
4 TGlobalVar.isAddApplication = false;
5 TGlobalVar.isAddMainWindow = false;

有了这些,我们就可以用来显示图片了~~

 

二,用于显示图片的TImage类

上面我们已经把一些公有属性都保存好了,因此我们要实现绘画就很简单了。先看TImage类的代码:

 1 function TImage(){
 2     var self = this;
 3     
 4     self.type = "TImage";
 5     self.x = 0;
 6     self.y = 0;
 7     self.scaleX = 1;
 8     self.scaleY = 1;
 9     self.isLoadComplete = false;
10     self.content = null;
11     self.sx = 0;
12     self.sy = 0;
13     self.swidth = 0;
14     self.sheight = 0;
15     self.width = 0;
16     self.height = 0;
17     self.toSwidth = self.swidth;
18     self.toSheight = self.sheight;
19     self.toSx = self.sx;
20     self.toSy = self.sy;
21 }
22 TImage.prototype.load = function(u){
23     var self = this;
24     self.isLoadComplete = false;
25     self.content = new Image();
26     self.content.onload = function(){
27         self.content.onload = null;
28         self.swidth = self.content.width;
29         self.sheight = self.content.height;
30         self.width = self.content.width;
31         self.height = self.content.height;
32         self.isLoadComplete = true;
33     };
34     self.content.src = u;
35 };
36 TImage.prototype.draw = function(layer){
37     var self = this;
38     if(!layer)layer = TGlobalVar.TMainWindowObj;
39     layer.childList.push(self);
40     self.parent = layer;
41 };
42 TImage.prototype.scale = function(scaleX,scaleY){
43     var self = this;
44     
45     self.scaleX = scaleX || self.scaleX;
46     self.scaleY = scaleY || self.scaleY;
47 };
48 TImage.prototype.move = function(x,y){
49     var self = this;
50     
51     self.x = x || self.x;
52     self.y = y || self.y;
53 };
54 TImage.prototype.setProperties = function(sx,sy,swidth,sheight){
55     var self = this;
56     
57     self.toSwidth = swidth || self.swidth;
58     self.toSheight = sheight || self.sheight;
59     self.toSx = sx || self.sx;
60     self.toSy = sy || self.sy;
61 };
62 TImage.prototype.show = function(){
63     var self = this;
64     
65     if(self.isLoadComplete == false)return;
66     self.swidth = self.toSwidth || self.swidth;
67     self.sheight = self.toSheight || self.swidth;
68     self.sx = self.toSx || 0;
69     self.sy = self.toSy || 0;
70     self.width = self.swidth;
71     self.height = self.sheight;
72     
73     TGlobalVar.TApplicationObj.canvas.drawImage(
74         self.content,
75         self.sx,self.sy,
76         self.swidth,self.sheight,
77         self.x,self.y,
78         self.width*self.scaleX,
79         self.height*self.scaleY
80     );
81 };

这里面的代码不难理解,显示图片的部分主要在show函数中。要加载图片需要在load函数中加载,也就是说,要显示图片需要先load一遍。另外,为了show函数并不需要自己去调用,在TGlobalVar.TMainWindowObj.show里面已经自动调用了。不过要显示图片要调用draw函数,这个函数有个参数,这个参数代表显示层,不添的话就是默认的最底层,这个参数现在只能不赋值,因为现在还没实现到层次化这一部分。

要移动图片的话,调用move方法就可以了。参数:[x坐标, y坐标]

要设置显示部分图片调用setProperties就行了,参数是:[图片可视范围x, 图片可视范围y, 图片可视范围宽度, 图片可视范围高度]

要拉伸图片就调用scale函数,参数[x轴拉伸倍数, y轴拉伸倍数]

好了,我们有了TImage类,就来做个测试吧,测试代码:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="utf-8" />
 5 <title>显示一张图片</title>
 6 <script src="./TMain.js"></script>
 7 <script src="./TApplication.js"></script>
 8 <script src="./TMainWindow.js"></script>
 9 <script src="./TImage.js"></script>
10 <script>
11 function main(){
12     var app = new TApplication();
13     var mainwindow = new TMainWindow({
14         id:"tomatogame",
15         width:800,
16         height:600,
17         frameRate:50
18     });
19     mainwindow.init();
20     app.exec();
21     showImage();
22 }
23 function showImage(){
24     var img = new TImage();
25     img.load("./face.jpg");
26     img.draw();
27     img.move(20,20);
28     img.scale(0.5,0.8);
29     
30     var img2 = new TImage();
31     img2.load("./face.jpg");
32     img2.draw();
33     img2.move(150,150);
34     img2.setProperties(100,100,200,200);
35 }
36 </script>
37 </head>
38 <body onload="main()">
39     <canvas id="tomatogame"></canvas>
40 </body>
41 </html>

运行出来的界面如下:

over,是不是很简单?下一次我们来实现一下层次化效果。敬请期待~~

 

源代码下载:点击这里下载源代码

 

如果大家有不懂的地方,欢迎在文章下方留言。能看到你们的留言,是我最开心的事了~~如果文章有疏漏的地方,也欢迎指出,多谢大家的支持。

posted @ 2013-08-26 14:45  Shin-Knight  阅读(1869)  评论(2编辑  收藏  举报