什么是SLG呢?也就是Simulation Game的縮寫,即模擬策略游戲。
以我這種準骨灰級玩家的視點來看(鄙人88年開始玩FC,時年6歲),早期的SLG游戲,大體只是《三國志》(I由1985年開始發售)這類發布指令擴充軍備并戰斗的“命令下達式游戲”,并沒有什么分類上的難度。但自從《火焰紋章》(1990年開始發售)出現伊始,即策略游戲與傳統RPG的分野變得模糊起來,這種具有故事情節的戰棋策略游戲,同時兼具了SLG及RPG的雙特性,以后的歲月中人們習慣分類其為——SRPG,火焰系列也據此被后人視作SRPG的鼻祖游戲之一。但事實上講,此類游戲仍舊具備著傳統SLG那樣如同下棋般戰斗并采用回合制的特點,RPG的情節部分僅僅是作為游戲內容的補充罷了,始終擺脫不掉傳統策略游戲地圖-〉指令-〉戰斗的大框架,故此客觀上依然應被劃入了SLG范圍。再后來,隨著電腦的普及,如大眾軟件這些媒體雜志又把文明和模擬城市乃至美少女夢工廠這樣的游戲也劃分進SLG里,但按照現在的說法,足球經理、模擬人生應該是“SIM”,即單純的Simulation,而美少女夢工廠則是TCG——不過在日式游戲劃分中,這些依然都屬于SLG。
就鄙人看來,強分策略類游戲類型是沒有什么意義的,作為最初源泉的SLG是能夠包含SRPG、RTS種種分支的。就好比有的人是博士、有的人是碩士,但我們依舊可以將其統稱為“知識分子”,劃到一個大圈子里面去。又比如我們平時可能常說“上海人怎樣”、“北京人如何”,但當我說“中國人”時,自然能夠將這些都包羅其中,無論好壞,誰都脫身不得。 而在此類游戲中,包含策略因素的這個大圈子的統一稱謂,便是SLG無疑。
實際上,絕大多數英文站點也是將此類游戲統一丟到Simulation Game下的(包括模擬城市之類的純SIM),并沒有進行SRPG(Strategies Role Play Games)或RTS(Real-Time Strategy Game)乃至其余種種的細分。歸根究底,因為這些游戲近似的因素太多,在大多數時候已經難以區分其本來面貌,“名無實,實無名”,只能一概而論了。而今有不少新生代玩家喜歡硬分游戲種類,竊以為愚了。
——————————————————————————————————————————————————————————
閑話說了不少,現在開始進入正題。在本系列中,我將結合實例嘗試以Java實現典型戰棋類SLG的主要功能,本文為第0節,也就是準備章節。
看過我以前寫的RPG及ACT系列的朋友們,應該已對Java中2D圖形繪制功能有了初步的認識,在本文中,我將闡述如何令繪制的窗體而非組件響應鼠標事件,及如何在窗體中自定義非標準大小的鼠標指針,作為本系列的預備知識。
首先,我們都知道,在Java中可以通過Cursor組件自定義游標樣式,比如下圖有一組取材自Langrisser2的光標圖片。
在Java桌面開發中,我們可以通過分解這組圖片來得到小圖,以此來自定義鼠標光標。
但是有一個問題,這時無論圖片原始大小如何,至多也只能是32x32大小,如果超出這個范圍,則無法作為游標在窗體中完整顯示。
也就是說,如上圖這樣46x46的大圖,要么縮小顯示,要么局部顯示,總之46x46的狀態下是無法完整的顯示在窗體中的。
可我們明明見到很多游戲中的光標是不規則不成比例的,究竟如何做到呢?其實很簡單,自己繪制就好了。
絕大多數不合規矩的東西,我們都可以自己把它“畫出來”,只要能確定它的坐標。
如下代碼記錄了鍵盤及鼠標狀態下的圖標移動:
此時,我們只需將光標在指定位置drawImage一下,自然就會得到想要的結果。但是有一點需要注意,那就是系統的Cursor此時還存在,如果我們不進行處理,畫面上會出現兩個游標的尷尬局面。但是Java并沒有提供給我們直接取消光標的方法,這時該怎么辦呢?很簡單,我們將其“隱形”即可。
比如這樣:
我們繪制一張16x16的透明圖作為游標,在使用者看來,就只能見到我們drawImage出的“偽游標”罷了。
現在我們據此制作一個假單的仿Langrisser2開始界面,代碼如下:
運行效果如下圖:
當您看見此行文字時,我的CSDN上傳功能還無法使用……
以我這種準骨灰級玩家的視點來看(鄙人88年開始玩FC,時年6歲),早期的SLG游戲,大體只是《三國志》(I由1985年開始發售)這類發布指令擴充軍備并戰斗的“命令下達式游戲”,并沒有什么分類上的難度。但自從《火焰紋章》(1990年開始發售)出現伊始,即策略游戲與傳統RPG的分野變得模糊起來,這種具有故事情節的戰棋策略游戲,同時兼具了SLG及RPG的雙特性,以后的歲月中人們習慣分類其為——SRPG,火焰系列也據此被后人視作SRPG的鼻祖游戲之一。但事實上講,此類游戲仍舊具備著傳統SLG那樣如同下棋般戰斗并采用回合制的特點,RPG的情節部分僅僅是作為游戲內容的補充罷了,始終擺脫不掉傳統策略游戲地圖-〉指令-〉戰斗的大框架,故此客觀上依然應被劃入了SLG范圍。再后來,隨著電腦的普及,如大眾軟件這些媒體雜志又把文明和模擬城市乃至美少女夢工廠這樣的游戲也劃分進SLG里,但按照現在的說法,足球經理、模擬人生應該是“SIM”,即單純的Simulation,而美少女夢工廠則是TCG——不過在日式游戲劃分中,這些依然都屬于SLG。
就鄙人看來,強分策略類游戲類型是沒有什么意義的,作為最初源泉的SLG是能夠包含SRPG、RTS種種分支的。就好比有的人是博士、有的人是碩士,但我們依舊可以將其統稱為“知識分子”,劃到一個大圈子里面去。又比如我們平時可能常說“上海人怎樣”、“北京人如何”,但當我說“中國人”時,自然能夠將這些都包羅其中,無論好壞,誰都脫身不得。 而在此類游戲中,包含策略因素的這個大圈子的統一稱謂,便是SLG無疑。
實際上,絕大多數英文站點也是將此類游戲統一丟到Simulation Game下的(包括模擬城市之類的純SIM),并沒有進行SRPG(Strategies Role Play Games)或RTS(Real-Time Strategy Game)乃至其余種種的細分。歸根究底,因為這些游戲近似的因素太多,在大多數時候已經難以區分其本來面貌,“名無實,實無名”,只能一概而論了。而今有不少新生代玩家喜歡硬分游戲種類,竊以為愚了。
——————————————————————————————————————————————————————————
閑話說了不少,現在開始進入正題。在本系列中,我將結合實例嘗試以Java實現典型戰棋類SLG的主要功能,本文為第0節,也就是準備章節。
看過我以前寫的RPG及ACT系列的朋友們,應該已對Java中2D圖形繪制功能有了初步的認識,在本文中,我將闡述如何令繪制的窗體而非組件響應鼠標事件,及如何在窗體中自定義非標準大小的鼠標指針,作為本系列的預備知識。
首先,我們都知道,在Java中可以通過Cursor組件自定義游標樣式,比如下圖有一組取材自Langrisser2的光標圖片。

在Java桌面開發中,我們可以通過分解這組圖片來得到小圖,以此來自定義鼠標光標。
但是有一個問題,這時無論圖片原始大小如何,至多也只能是32x32大小,如果超出這個范圍,則無法作為游標在窗體中完整顯示。
也就是說,如上圖這樣46x46的大圖,要么縮小顯示,要么局部顯示,總之46x46的狀態下是無法完整的顯示在窗體中的。
可我們明明見到很多游戲中的光標是不規則不成比例的,究竟如何做到呢?其實很簡單,自己繪制就好了。
絕大多數不合規矩的東西,我們都可以自己把它“畫出來”,只要能確定它的坐標。
如下代碼記錄了鍵盤及鼠標狀態下的圖標移動:
- /**
- *鍵盤事件設置
- *
- */
- public void setKeyset(){
- addKeyListener( new KeyAdapter(){
- public void keyTyped(KeyEvente){
- }
- public void keyReleased(KeyEvente){
- }
- public void keyPressed(KeyEvente){
- if (e.getKeyCode()==KeyEvent.VK_RIGHT){
- currentX=currentX+move;
- }
- if (e.getKeyCode()==KeyEvent.VK_LEFT){
- currentX=currentX-move;
- }
- if (e.getKeyCode()==KeyEvent.VK_UP){
- currentY=currentY-move;
- }
- if (e.getKeyCode()==KeyEvent.VK_DOWN){
- currentY=currentY+move;
- }
- repaint();
- }
- });
- }
- /**
- *鼠標事件設置
- *
- */
- public void setMouse(){
- addMouseListener( new MouseAdapter(){
- public void mousePressed(MouseEvente){
- }
- public void mouseReleased(MouseEvente){
- }
- });
- addMouseMotionListener( new MouseMotionAdapter(){
- public void mouseMoved(MouseEventex){
- currentX=ex.getX();
- currentY=ex.getY();
- repaint();
- }
- public void mouseDragged(MouseEventex){
- currentX=ex.getX();
- currentY=ex.getY();
- repaint();
- }
- });
- }
比如這樣:
- CursorFramef= new CursorFrame();
- int []pixels= new int [ 256 ];
- Imageimage=Toolkit.getDefaultToolkit().createImage(
- new MemoryImageSource( 16 , 16 ,pixels, 0 , 16 ));
- CursortransparentCursor= Toolkit.getDefaultToolkit()
- .createCustomCursor(image, new Point( 0 , 0 ), "hidden" );
- f.setCursor(transparentCursor);
我們繪制一張16x16的透明圖作為游標,在使用者看來,就只能見到我們drawImage出的“偽游標”罷了。
現在我們據此制作一個假單的仿Langrisser2開始界面,代碼如下:
- package org.slg.simple;
- import java.awt.Color;
- import java.awt.Cursor;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Image;
- import java.awt.Panel;
- import java.awt.Point;
- import java.awt.Toolkit;
- import java.awt.event.KeyAdapter;
- import java.awt.event.KeyEvent;
- import java.awt.event.MouseAdapter;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseMotionAdapter;
- import java.awt.image.BufferedImage;
- import java.awt.image.MemoryImageSource;
- /**
- *Copyright2008
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");youmaynot
- *usethisfileexceptincompliancewiththeLicense.Youmayobtainacopyof
- *theLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,WITHOUT
- *WARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.Seethe
- *Licenseforthespecificlanguagegoverningpermissionsandlimitationsunder
- *theLicense.
- *
- *@projectloonframework
- *@authorchenpeng
- *@email:ceponline@yahoo.com.cn
- *@version0.1
- */
- public class ExemplePanel extends Panel{
- /**
- *
- */
- private static final long serialVersionUID=1L;
- final static int currentWidth= 480 ;
- final static int currentHeight= 360 ;
- //背景緩沖圖
- final Image_background;
- //鼠標指針圖形組
- final Image[]_mouses;
- //背景圖
- final Image_backgroundImage;
- Graphics_backgroundGraphics;
- Image_mouse;
- Image_arrow;
- //選中項,默認指向第一條
- int _select= 1 ;
- //游標x軸
- int _currentX= 0 ;
- //游標y軸
- int _currentY= 0 ;
- int _move= 5 ;
- public ExemplePanel(){
- //創建一個背景緩存用image
- _background= new BufferedImage(currentWidth,currentHeight,
- BufferedImage.TYPE_INT_ARGB);
- //導入開始時背景圖像
- _backgroundImage=Utility.loadImage( "image/start.gif" );
- //導入光標圖系列,以列寬46讀取到image數組
- _mouses=Utility.getImageColumns(
- Utility.loadImage( "image/cursor.png" ), 46 );
- //初始背景為黑色
- setBackground( new Color( 0 , 0 , 0 ));
- _arrow=Utility.loadImage( "image/arrow.png" );
- _backgroundGraphics=_background.getGraphics();
- //設定鍵盤監聽
- setKeyset();
- //設定鼠標監聽
- setMouse();
- //設置鼠標動畫(本例只是一個簡單示例,實際應根據相應事件變更游標造型)
- ThreadmouseAnimation= new Thread(){
- public void run(){
- int cursorMax=_mouses.length;
- int cursorIndex= 0 ;
- do {
- if (cursorIndex<cursorMax){
- _mouse=_mouses[cursorIndex];
- try {
- Thread.sleep( 500 );
- } catch (InterruptedExceptione){
- e.printStackTrace();
- }
- repaint();
- } else {
- cursorIndex= 0 ;
- }
- cursorIndex++;
- } while ( true );
- }
- };
- //開啟鼠標動畫
- mouseAnimation.start();
- }
- public void paint(Graphicsg){
- //繪制背景
- _backgroundGraphics.drawImage(_backgroundImage, 0 , 0 , this );
- //繪制光標
- _backgroundGraphics.drawImage(_mouse,_currentX,_currentY, this );
- drawTitle((Graphics2D)_backgroundGraphics);
- //加載緩存圖
- g.drawImage(_background, 0 , 0 , this );
- }
- public void update(Graphicsg){
- paint(g);
- }
- /**
- *鍵盤事件設置
- *
- */
- public void setKeyset(){
- addKeyListener( new KeyAdapter(){
- public void keyTyped(KeyEvente){
- }
- public void keyReleased(KeyEvente){
- }
- public void keyPressed(KeyEvente){
- if (e.getKeyCode()==KeyEvent.VK_RIGHT){
- _currentX=_currentX+_move;
- }
- if (e.getKeyCode()==KeyEvent.VK_LEFT){
- _currentX=_currentX-_move;
- }
- if (e.getKeyCode()==KeyEvent.VK_UP){
- _currentY=_currentY-_move;
- }
- if (e.getKeyCode()==KeyEvent.VK_DOWN){
- _currentY=_currentY+_move;
- }
- repaint();
- }
- });
- }
- /**
- *鼠標事件設置
- *
- */
- public void setMouse(){
- int []pixels= new int [ 256 ];
- Imageimage=Toolkit.getDefaultToolkit().createImage(
- new MemoryImageSource( 16 , 16 ,pixels, 0 , 16 ));
- //制作一個透明的游標
- CursortransparentCursor=Toolkit.getDefaultToolkit()
- .createCustomCursor(image, new Point( 0 , 0 ), "hidden" );
- //插入透明游標,以此模擬無游標狀態
- setCursor(transparentCursor);
- addMouseListener( new MouseAdapter(){
- public void mousePressed(MouseEvente){
- if (e.getButton()== 1 ){
- State.l_clk= true ;
- }
- if (e.getButton()== 3 ){
- State.r_clk= true ;
- }
- }
- public void mouseReleased(MouseEvente){
- if (e.getButton()== 1 ){
- State.l_clk= false ;
- }
- if (e.getButton()== 3 ){
- State.r_clk= false ;
- }
- }
- });
- addMouseMotionListener( new MouseMotionAdapter(){
- public void mouseMoved(MouseEventex){
- _currentX=ex.getX();
- _currentY=ex.getY();
- repaint();
- }
- public void mouseDragged(MouseEventex){
- _currentX=ex.getX();
- _currentY=ex.getY();
- repaint();
- }
- });
- }
- /**
- *繪制標題選項
- *
- *@paramg
- */
- void drawTitle(Graphics2Dg){
- Utility.font(g, 15 , 1 );
- Utility.color(g, 0 , 0 , 0 );
- if (_select!= 0 ){
- g.drawImage(_arrow, 168 , 227 +_select* 20 , null );
- }
- //PS:如果不想在程序中繪制,也可以直接在準備好的背景圖上寫文字,pc版的Langrisser就是那樣......
- g.drawString( "開始新游戲" , 195 , 260 );
- g.drawString( "載入記錄" , 203 , 280 );
- g.drawString( "退出游戲" , 203 , 300 );
- for ( int i= 0 ;i< 3 ;i++){
- if (_currentX> 195 &&_currentX< 270 &&_currentY>i* 20 + 235
- &&_currentY<i* 20 + 275 ){
- _select=i+ 1 ;
- }
- }
- repaint();
- Utility.wait( 20 );
- if (State.l_clk&&!State.lock_lck){
- State.lock_lck= true ;
- if (_select== 1 ){
- System.out.println( "您選擇了:開始" );
- }
- if (_select== 2 ){
- System.out.println( "您選擇了:繼續" );
- }
- if (_select== 3 ){
- System.out.println( "您選擇了:結束" );
- System.exit( 0 );
- }
- }
- if (!State.l_clk&&State.lock_lck){
- State.lock_lck= false ;
- }
- }
- }
運行效果如下圖:
![Java版SLG游戲開發入門[0]--讓繪制的窗口響應鼠標事件](http://img.it610.com/image/product/ddb5c1b9c109486b971da0067bd938f3.jpg)
當您看見此行文字時,我的CSDN上傳功能還無法使用……
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
