Java版AVG游戲開發入門[0]——游戲模式轉換中的事件交互

Java版AVG游戲開發入門[0]——游戲模式轉換中的事件交互

?? 示例程序下載地址:http://download.csdn.net/source/999273(源碼在jar內)

?

?AVG,即Adventure Game,可以直譯為[冒險游戲]。但是通常情況下我們說AVG是指[文字冒險游戲],也有人更直白的解釋成自己選擇路線和結局的電子小說,與硬砍硬殺的RPG或者揉破鍵盤的ACT不同,AVG多以解謎或文字游戲等腦力攻關推動劇情發展。現在日本流行的ADV,可以看作是AVG英文全稱的不同縮寫方式,大體上講,AVG == ADV

?

?由于商業化需要,現代主流的AVG往往是GalGame,也就是少女游戲,或稱少女戀愛游戲,但GalGame != AVG,只是下屬分支中的一環罷了,AVG包含GalGame,但GalGame并不能完全代表AVG/ADV。另外關于GalGame的詳細介紹,在若木民喜《只有神才知道的世界》中演繹的相當生動,有興趣的可以自己去看看~

?

? 《只有神知道的世界》漫畫圖

?

??就技術角度而言,AVG開發可以算得所有游戲類型中最容易的。一款簡單AVG游戲的制作難度甚至在貪食蛇、俄羅斯方塊之下。由于實現的簡易性,導致AVG的開發重心往往著重于策劃及美工,程序員的作用則微乎其微。同時也正因AVG開發的門坎約等于0,所以此類型的同人游戲之多即可堪稱世界之冠。另外,AVG開發工具普及的也促進了AVG的量產化。利用工具,即始是小說作者、漫畫家等非軟件專業出身的人士,往往也能輕易制作出頂級的AVG大作。(順便一提,目前我所見過最好的AVG制作工具是鬼子的livemaker,采用類似思維導圖的方式構造整個游戲,很多輕小說作者乃至網絡漫畫家用它制作自己作品的宣傳游戲。但就技術角度上說,livemaker的開發依舊沒什么難度......

?

?由于AVG的大泛濫,通常僅有文字、圖片及語音的AVG往往無法滿足用戶需求(H除外-_-)。我們每每可在AVG游戲類型后發現個+號,比如《櫻花大戰》是AVG+SLG,《生化危機》是AVG+ACT。所以客觀上說,AVG開發僅僅能進行字圖的交互是不夠的,還要解決多模塊組件的協調問題。

?

?Java桌面應用開發中,我們都知道繪圖是極為簡單的,有ImageGraphics兩個對象就可以Paint一個圖形,即使圖形對象再多,最后它們也必須統一在一個Paint中,所以Java中不存在圖像的交互問題。

?

但問題在于,圖像的顯示可以統一,但是觸發圖像變化的事件卻是很難統一的。比如現在有需求如下,在AVG模式中,觸發鍵盤事件上、下、左、右時為控制畫面的前進、后退,切換模式到SLG模式后,設定上、下、左、右是光標移動,那么如果我要在程序中實現,就必須記錄當前模式,而后根據不同模式調用事件,再反饋到圖形上。如果只有幾個事件的區別,我們當然可以很容易用分支來實現;問題是,隨著游戲規模的加大,這些分支將成幾何倍數增多,單純的分支判定到最后只能忙于應付,落個費力不討好。

?

其實在這時,我們大可以使用一些技巧來輕松解決問題。

?

示例如下:

?

?

首先,我們構造一個接口,命名為IControl,繼承鼠標及鍵盤監聽,并在其中設定兩個抽象方法:

?

??? package org.loon.simple.avg; import java.awt.Graphics; import java.awt.event.KeyListener; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; /** * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:ceponline@yahoo.com.cn * @version 0.1 */ public interface IControl extends MouseListener, MouseMotionListener, KeyListener { public abstract void draw(final Graphics g); public abstract IControl invoke(); }

?

?

? 而后,再構造一個接口,命名為IAVG,同樣繼承鼠標及鍵盤監聽,并在其中設定三個抽象方法,用以操作IControl接口:


??? package org.loon.simple.avg; import java.awt.Graphics; import java.awt.event.KeyListener; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; /** * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:ceponline@yahoo.com.cn * @version 0.1 */ public interface IAVG extends MouseListener, MouseMotionListener, KeyListener { public abstract void draw(final Graphics g); public abstract IControl getControl(); public abstract void setControl(final IControl control); }?


???? 再后,制作一個顯示圖像用組件,命名為AVGCanva,繼承自Canvas。

?

???? package org.loon.simple.avg; import java.awt.Canvas; import java.awt.Graphics; /** * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:ceponline@yahoo.com.cn * @version 0.1 */ public class AVGCanvas extends Canvas { /** * */ private static final long serialVersionUID = 1982278682597393958L; private boolean start; private IAVG avg; public AVGCanvas(IAVG handler) { this.avg = handler; this.start = false; this.addKeyListener(handler); this.addMouseListener(handler); this.addMouseMotionListener(handler); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { if (this.start) { this.avg.draw(g); } } public void startPaint() { this.start = true; } public void endPaint() { this.start = false; } }

?

???? 這段代碼中的paint方法中并沒有現成的方法,而是調用了IAVG接口的draw。緊接著,我們再設定一個AVGFrame用以加載AVGCanvas。

?

??? package org.loon.simple.avg; import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; /** * Copyright 2008 - 2009 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loonframework * @author chenpeng * @email:ceponline@yahoo.com.cn * @version 0.1 */ public class AVGFrame extends Frame implements Runnable { /** * */ private static final long serialVersionUID = 198284399945549558L; private IAVG avg; private AVGCanvas canvas; private boolean fps; private String titleName; private Thread mainLoop; public AVGFrame(String titleName, int width, int height) { this(new AVG(), titleName, width, height); } public AVGFrame(IAVG avg, String titleName, int width, int height) { super(titleName); Lib.WIDTH = width; Lib.HEIGHT = height; this.avg = avg; this.titleName = titleName; this.addKeyListener(avg); this.setPreferredSize(new Dimension(width + 5, height + 25)); this.initCanvas(Lib.WIDTH, Lib.HEIGHT); this.pack(); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); this.setResizable(false); this.setLocationRelativeTo(null); this.setVisible(true); } public void run() { gameLoop(); } /** * 開始循環窗體圖像 * */ private synchronized void gameLoop() { canvas.startPaint(); long second = 0L; int moveCount = 0; // 循環繪制 for (;;) { long start = System.currentTimeMillis(); this.paintScreen(); long end = System.currentTimeMillis(); long time = end - start; long sleepTime = 20L - time; if (sleepTime < 0L) sleepTime = 0L; try { Thread.sleep(sleepTime); } catch (InterruptedException e) { e.printStackTrace(); } if (this.fps) { moveCount++; second += System.currentTimeMillis() - start; if (second >= 1000L) { this.setTitle(new StringBuilder(titleName).append(" FPS:") .append(moveCount).toString()); moveCount = 0; second = 0L; } } } } /** * 啟動游戲循環 * */ public void mainLoop() { this.mainLoop = new Thread(this); this.mainLoop.start(); } /** * 初始化背景帆布 * * @param width * @param height */ private void initCanvas(final int width, final int height) { canvas = new AVGCanvas(avg); canvas.setBackground(Color.black); canvas.setPreferredSize(new Dimension(width, height)); this.add(canvas); } public IAVG getAVG() { return this.avg; } protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); } public synchronized void paintScreen() { canvas.repaint(); } public boolean isShowFPS() { return fps; } public void setShowFPS(boolean fps) { this.fps = fps; } public Thread getMainLoop() { return mainLoop; } public String getTitleName() { return titleName; } }

?

? 我們可以看到,在本例鼠標鍵盤事件及圖像繪制完全通過接口方式實現。此時,只要讓不同組件統一實現IControl接口,便可以輕松轉換事件及圖像的繪制。也正是我們都再熟悉不過的MVC模式中,通過Event導致Controller改變ModelView的基本原理。

?

?? 下一回,我們將具體講解一個AVG游戲實現的基本流程。

?

? 示例代碼界面如下圖:

?

? 初始界面

?

?

?人物對話

?

? 問題選擇

?

? 小游戲切換

?

? 不同游戲模式切換

?

?? 示例程序下載地址:http://download.csdn.net/source/999273(源碼在jar內)

?

posted on 2009-02-08 10:06 cping 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/cping1982/archive/2009/02/08/2257949.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379761.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379761.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379761.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

FreeRTOS任務創建和刪除

任務創建和刪除的API函數 xTaskCreate()&#xff1a;使用動態方法創建一個任務xTaskCreateStatic()&#xff1a;使用靜態方法創建一個任務xTaskCreateRestricated()&#xff1a;創建一個使用MPU進行限制的任務&#xff0c;相關內存使用動態內存分配vTaskDelete()&#xff1a;刪…

Delphi 調試

調試&#xff1a;F9執行F8逐過程單步調試F7逐語句單步調試轉載于:https://www.cnblogs.com/JackShao/archive/2012/04/30/2476931.html

1.創建單項鏈表

# include <stdio.h> # include <malloc.h> # include <stdlib.h>typedef struct Node{int data;//數據域struct Node *pNext;//指針域}NODE, *PNODE; //NODE等價于struct Node //PNOD等價于struct Node * //函數聲明PNODE create_list(void); void traverse…

python 日本就業_日本的繪圖標志 Python中的圖像處理

python 日本就業Read basics of the drawing/image processing in python: Drawing flag of Thailand 閱讀python中繪圖/圖像處理的基礎知識&#xff1a; 泰國的繪圖標志 The national flag of Japan is a rectangular white banner bearing a crimson-red disc at its center…

[windows phone 7 ]查看已安裝程序GUID

首先介紹下wp7RootToolsSDK,這個功能相當強大&#xff0c;適合研究wp7高級功能。 它支持File&#xff0c;Register操作&#xff0c;比之前的COM調用要簡單&#xff0c;方便。 功能:查看已安裝程序的guid 開發心得: 用的是mozart,rom多&#xff0c;刷機吧&#xff0c;最麻煩的是…

FreeRTOS任務掛起和恢復

任務掛起&#xff1a;暫停某個任務的執行 任務恢復&#xff1a;讓暫停的任務繼續執行 通過任務掛起和恢復&#xff0c;可以達到讓任務停止一段時間后重新運行。 相關API函數&#xff1a; vTaskSuspend void vTaskSuspend( TaskHandle_t xTaskToSuspend );xTaskToSuspend &am…

向oracle存儲過程中傳參值出現亂碼

在頁面中加入<meta http-equiv"Content-Type" content"text ml;charsetUTF-8"/>就可以解決這一問題 適用情況&#xff1a; 1.中文 2.特殊符號 轉載于:https://www.cnblogs.com/GoalRyan/archive/2009/02/16/1391348.html

Scala程序將多行字符串轉換為數組

Scala | 多行字符串到數組 (Scala | Multiline strings to an array) Scala programming language is employed in working with data logs and their manipulation. Data logs are entered into the code as a single string which might contain multiple lines of code and …

SQL 異常處理 Begin try end try begin catch end catch--轉

SQL 異常處理 Begin try end try begin catch end catch 總結了一下錯誤捕捉方法:try catch ,error, raiserror 這是在數據庫轉換的時候用的的異常處理, Begin TryInsert into SDT.dbo.DYEmpLostTM(LogDate,ProdGroup,ShiftCode,EmployeeNo,MONo,OpNo,OTFlag,LostTypeID,OffStd…

FreeRTOS中斷配置與臨界段

Cortex-M中斷 中斷是指計算機運行過程中&#xff0c;出現某些意外情況需主機干預時&#xff0c;機器能自動停止正在運行的程序并轉入處理新情況的程序&#xff08;中斷服務程序&#xff09;&#xff0c;處理完畢后又返回原被暫停的程序繼續運行。Cortex-M內核的MCU提供了一個用…

vector向量容器

一、vector向量容器 簡介&#xff1a; Vector向量容器可以簡單的理解為一個數組&#xff0c;它的下標也是從0開始的&#xff0c;使用時可以不用確定大小&#xff0c;但是它可以對于元素的插入和刪除&#xff0c;可以進行動態調整所占用的內存空間&#xff0c;它里面有很多系統…

netsh(二)

netsh 來自微軟的網絡管理看家法寶很多時候&#xff0c;我們可能需要在不同的網絡中工作&#xff0c;一遍又一遍地重復修改IP地址是一件比較麻煩的事。另外&#xff0c;系統崩潰了&#xff0c;重新配置網卡等相關參數也比較煩人&#xff08;尤其是無線網卡&#xff09;。事實上…

java uuid靜態方法_Java UUID getLeastSignificantBits()方法與示例

java uuid靜態方法UUID類getLeastSignificantBits()方法 (UUID Class getLeastSignificantBits() method) getLeastSignificantBits() method is available in java.util package. getLeastSignificantBits()方法在java.util包中可用。 getLeastSignificantBits() method is us…

Google C2Dm相關文章

Android C2DM學習——云端推送&#xff1a;http://blog.csdn.net/ichliebephone/article/details/6591071 Android C2DM學習——客戶端代碼開發&#xff1a;http://blog.csdn.net/ichliebephone/article/details/6626864 Android C2DM學習——服務器端代碼開發&#xff1a;http…

FreeRTOS的列表和列表項

列表和列表項 列表 列表是FreeRTOS中的一個數據結構&#xff0c;概念上和鏈表有點類型&#xff0c;是一個循環雙向鏈表&#xff0c;列表被用來跟蹤FreeRTOS中的任務。列表的類型是List_T&#xff0c;具體定義如下&#xff1a; typedef struct xLIST {listFIRST_LIST_INTEGRI…

string基本字符系列容器

二、string基本字符系列容器 簡介&#xff1a;C語言只提供了一個char類型來處理字符&#xff0c;而對于字符串&#xff0c;只能通過字符串數組來處理&#xff0c;顯得十分不方便。CSTL提供了string基本字符系列容器來處理字符串&#xff0c;可以把string理解為字符串類&#x…

正則表達式(一)

正則表達式概述 1.1什么是正則表達式&#xff1f; 正則表達式(Regular Expression)起源于人類神經系統的早期研究。神經生理學家Warren McCulloch和Walter Pitts研究出一種使用數學方式描述神經網絡的方法。1956年&#xff0c;數學家Stephen Kleene發表了一篇標題為“神經…

42.有“舍”才有“得”

大干世界&#xff0c;萬種誘惑&#xff0c;什么都想要&#xff0c;會累死你&#xff0c;該放就放&#xff0c;該舍就舍。人必須先有所舍&#xff0c;才能有所得&#xff0c;舍如同種子撒播出去&#xff0c;轉了一圈&#xff0c;又帶了一大群子子孫孫回來。“舍”永遠在“得”的…

Java StringBuilder codePointCount()方法與示例

StringBuilder類codePointCount()方法 (StringBuilder Class codePointCount() method) codePointCount() method is available in java.lang package. codePointCount()方法在java.lang包中可用。 codePointCount() method is used to count the number of Unicode code point…

FreeRTOS時間管理

在使用FreeRTOS的過程中&#xff0c;我們通常會在一個任務函數中使用延時函數對這個任務延時&#xff0c;當執行延時函數的時候就會進行任務切換&#xff0c;并且此任務就會進入阻塞太&#xff0c;直到延時完成&#xff0c;任務重新進入就緒態。延時函數舒屬于FreeRTOS的時間管…