J2ME中使用Canvas制作简单的游戏菜单

来源:百度文库 编辑:神马文学网 时间:2024/05/01 16:59:00
我们知道MIDP的图形用户界面分为两类,分别是高级图形用户界面和低级用户界面。一般来讲高级图形用户界面类使用起来比较方便,可移植性强,但是程序员对他的控制能力也很低,因为它们的界面表现是由底层控制的,而不是我们控制的。相比高级UI类,低级UI类则使用起来更难一些,但是控制能力更强,可以做出自己需要的界面。 帓?*藑
钉j糩畠
Canvas和Graphics是我们必须熟练使用的两个类,分别代表了画布和画笔(事实上更丰富,姑且这么比喻)。而我们则是画画的人,而指导我们如何下笔的就是java doc了,再加上勤奋努力一定可以画出不错的界面。比如tabbed菜单,二级菜单等。这里我们讲述一个简单菜单的制作方式。 \幢v?胖柇
摻€R碢[/9
在画菜单的时候,需要考虑两面的问题,第一是计算相对位置,让菜单能够尽可能适应更多的机型,尽量少使用绝对值。例如画下面的菜单的时候 ]DPa;5A
輿8揲?`
我们应该计算菜单的每个条目的高度,这些可以有Font的高度算出,当然你可以给条目留一些padding的距离。还应该计算条目的最宽值,毕竟每个条目的字数不一样。这样基本知道了整个菜单占的空间。最后还需要计算菜单在屏幕的位置。菜单的绘制如下所示: TKf楱祸i
j喕I鶎逊{?
public void paint(Graphics g){ 1湌.趈?
+?G‘,Y??
//清除屏幕 產/兢覱?:
縏臢鲮
int color = g.getColor(); 佂膴lPI请T
9R逖篂p#0`
g.setColor(0xFFFFFF); 癚コM緪聯
躪>?恩:?
g.fillRect(0,0,getWidth(),getHeight()); 3迟9hz鸿蕋
}l?鎬A
g.setColor(color); D嘣?)赿
D f领@晳夙
//计算整个菜单的高度,宽度和(x,y) db硵]孨
帧e(~|F:eI
int rectWidth = preferWidth; O陮煫剄p$u
珀+砦0?@?
int rectHeight = preferHeight * LABELS.length; fo?n@7]/
矡鴃?
int x = (getWidth()-rectWidth)/2; 鮃懇q憕?
罎诬| 饜7
int y = (getHeight()-rectHeight)/2; 豅?執N pA
硒+y?聽?
//画矩形 €亶橳投?
??LZ柌?
g.drawRect(x,y,rectWidth,rectHeight); ?O懙↙验7
琾?醃;l3
for(int i = 1;i钲vユ??
g.drawLine(x,y+preferHeight*i,x+rectWidth,y+preferHeight*i); |0?‘愓l,
婳見~紌?
} 讏X?j-蝹
V爔?
//画菜单选项,并根据selected的值判断焦点 郏/釄嫙m@
R崭?┅骑
for(int j = 0;j?鹤?
if(selected == j){ t?m挧?
I-??淗
g.setColor(0x6699cc); R憄?o9tq
md`_間隩_
g.fillRect(x+1,y+j*preferHeight+1,rectWidth-1,preferHeight-1); 妽G)?!揔$?
磫橅f棂﨤V
g.setColor(color); 嵜*H癷儩?
;縃‘P? ?
} 藤果槇櫫?
u訐BiO?
g.drawString(LABELS[j],x+8,y+j*preferHeight+4,Graphics.LEFT|Graphics.TOP); 時滊H[m昜
獇BD蚀拆?
} 3z壜5圭#?
^姄~3q,H?
} 迡I?R$?
Eb?6M
第二个重要的问题是:焦点的切换,在高级UI类中,这是不需要我们处理的。但是使用Canvas制作菜单需要自己来处理焦点的移动,这里我们定义一个int类型变量selected,来记录焦点所在的菜单条目位置,也就是选择的索引。当用户按键的时候,我们在keyPressed()方法中判断用户的移动方向,对selected进行相关的加减运算,然后repaint()整个屏幕即可。 j氲皾?
7?QG焸$K?
public void keyPressed(int keyCode){ 儓亭?2
桘[殛?
//根据用户输入更新selected的值,并重新绘制屏幕 ‘6噡$J
柴耻簀9鱱?
int action = this.getGameAction(keyCode); x???齮
崶??跷
switch(action){ 砓羓"?
s?郑墄&
case Canvas.FIRE: !浓1?X?
浭週f?W(?
printLabel(selected); 088涮焂U?
詫Te_佶
break; O轗P)pd?
b|梦壋絊
case Canvas.DOWN: 桄?囦梠
?靂u箼4
selected = (selected+1)%4; [u赠耙Ge?
殂?蹼抻)4
break; E;?缉yㄣT
勥K>铿??
case Canvas.UP:{ ~/?
庴顯睴?}‘
if(--selected < 0){ X扤h籑C
‘<奇?維?
selected+=4; ?撛嶩?
拔铅?W坆
} !2咍P#摡
頃:堚?
break; ^_F=?厺?
)U?矏?
} 僺轷=\蓡
e螛xC簅3
default: ~"W經 :B
‘?鉩謄鰟?
break; 戰P\q研
t`Vgr覮,
} 岏淜J歔M?
=c&┴D
repaint(); B昕∽Iみ
蠱1综Rr袓?
serviceRepaints(); #嘇??m
D?踌o4?
} 崴???輻
mj8YU.y艌?
这样我们就制作出了一个基本的菜单,你还可以发挥想象给被选中的菜单增加动画效果。MenuCanvas的代码如下所示: ズO??R
4ω^kR??
package com.j2medev.chapter3; S:鴠 €
d?沙?H
import javax.microedition.lcdui.*; 訬鬽 d=?
N悷 莻?
public class MenuCanvas extends Canvas{ 1牳歲缢frS
@V讜}O惨O?
//selected变量标记了焦点位置 腮)U??
o?lt;|+t厒
private int selected = 0; {S陓絽嗈3
瞴歌`?
private int preferWidth = -1; H?yN剠蛑r
W?&浪f
private int preferHeight = -1; N+獺XP?_
澭 x囂W?W
public static final int[] OPTIONS = {0,1,2,3}; r媞斚?
~锴?I惔鷟
public static final String[] LABELS={"New Game","Setttings","High Scores","Exit"}; >Z踝礻b?
public MenuCanvas() { `m~鐚磪G簅
vc*訥{?
selected = OPTIONS[0]; 寽gO潇溁
O喍綂厠?Y
//计算菜单选项的长度和高度值 D諽_m=b儫?
淃W?ys?
Font f = Font.getDefaultFont(); @4?醹Y?
;砸??
for(int i = 0;io泦G宷瓊M?
int temp = f.stringWidth(LABELS); K_qtと
鉋s99 囋
if(temp > preferWidth){ H??瑅償?
Jkt?T)︻
preferWidth = temp; 洇瀶塂?龈
鰿?DU_b
} oD?:6?
?d0辄涳q
} 璤z腳对兝
E貹qE嚥A?
preferWidth = preferWidth + 2*8; 韘疘9F.FY
琻璿Z屹
preferHeight = f.getHeight()+2*4; 揶L%?偑
;竍?n
} ~h旛?V?
w挗Gb矑c?
public void paint(Graphics g){ 掆揷2硻
哃結?Z?
//清除屏幕 G?YI巛?
)??lt;畾 ?
int color = g.getColor(); 楽邖Q烚瑴?
袨骍幝 v?
g.setColor(0xFFFFFF); 偮?LI
t%k筜&
g.fillRect(0,0,getWidth(),getHeight()); 搢Q嶺倆X?
u幒i閹?
g.setColor(color); 鍍N7):▲y?
坖@?勪N談
//计算整个菜单的高度,宽度和(x,y) |顸嶟m
5?烻8h‘
int rectWidth = preferWidth; 7唣鉀?
9?羺{
int rectHeight = preferHeight * LABELS.length; T?驫??
R狭窾?
int x = (getWidth()-rectWidth)/2; |sz u郢氋Q
呮 瑧?\厣
int y = (getHeight()-rectHeight)/2; I术l忈y?
7b+?DB胰o
//画矩形 t-?0c
輈3崠
g.drawRect(x,y,rectWidth,rectHeight); 堜JR-s[
=頰??
for(int i = 1;i蘋鱝$嘢?
g.drawLine(x,y+preferHeight*i,x+rectWidth,y+preferHeight*i); i菮~?L=戈
w?5({ 9
} O慞菷?鮪?
灿éx霦 P
//画菜单选项,并根据selected的值判断焦点 謖凾牝Wh爗
搨?訰,迍
for(int j = 0;jN┲?籧
if(selected == j){ r絻?棄巨?
A^7g.setColor(0x6699cc); b?rE]?
!?黿QS5
g.fillRect(x+1,y+j*preferHeight+1,rectWidth-1,preferHeight-1); S铺0儧?
<褟縲滄(U?
g.setColor(color); 祖?i湺??
I潄?p
} 埡訥j-m鵒?
l勓貎圓
g.drawString(LABELS[j],x+8,y+j*preferHeight+4,Graphics.LEFT|Graphics.TOP); 聞啺=u 醒?
I?秮W?
} %b嵩C[翓?
g濈~甼步
} 9?獠姣?
X?瓢?鷧
public void keyPressed(int keyCode){ 鷑筃k0@E陸
,翁?鋁
//根据用户输入更新selected的值,并重新绘制屏幕 @}H?*埙ex
唴钻?
int action = this.getGameAction(keyCode); =!`
庹`坸6/
switch(action){ 碋mc捀?_?
郜+2泍??
case Canvas.FIRE: 鶯?PU]丩&
亵劔j1蝞E
printLabel(selected); 鉡瓵犸B?
驫?
break; T衑 鼀5?\
勇W賏*?
case Canvas.DOWN: 袓? $_笍?
^?C>?
selected = (selected+1)%4; 苔9ⅹo娽?
nkgIA寎9
break; H`呱 zj?
}禄Pv??
case Canvas.UP:{ 怒遣?1囙?
j 搈?徱?
if(--selected < 0){ 蕭2狆X笳?
VX蠙?些1
selected+=4; nJjE?祉?
奭?|}獧
} 家?
啜f孚h淟W{
break; nf虚A叺5?
V?懚|M=w
} U?~?mD?
($洉影#=?
default: 抃砥?汩帤
&%E‘y%jZ?
break; 騢粉Dr韲
鈗L鏄 e\
} w6蟾陑
X粿A; c?
repaint(); 峤?蟩怼
蜓蓔鸅P速
serviceRepaints(); 錔?lt;?Q
/窶楟窀p
} 殥/i*?
咅<"疫x酂?
//showNotify()在paint()之前被调用 紙鰅?灊?
7Vl申]鞋‘Q
public void showNotify(){ Ё叀聅爧^?
?=q靄
System.out.println("showNotify() is called"); □ 椆齪曁
27a 概銂y!
} BG К=终
XY斅s菸
private void printLabel(int selected){ m业G
冖j@v?匌
System.out.println(LABELS[selected]); 忲k?罓=A?
6碝"t唅
} 弶ㄈ璜詂?
凲9n?W
}