android 2D游戏开发,引擎设计(三) 实验脚本编写与纸娃娃系统
2D紙娃娃
在以前沒(méi)有采用紙娃娃系統(tǒng)的游戲中,游戲角色的所有外觀都是游戲美工預(yù)先制作好的,因此數(shù)量有限,且占用較多資源(內(nèi)存,硬盤空間),比如為了實(shí)現(xiàn)同一角色拿著不同武器奔跑的圖像,開(kāi)發(fā)者不得不繪制兩套奔跑圖,分別加上不同的武器。而實(shí)際上,變化的只是武器,這樣多的一組奔跑圖像就是多余的。而紙娃娃系統(tǒng)就是針對(duì)此設(shè)計(jì)的。 在紙娃娃系統(tǒng)中,角色的每個(gè)動(dòng)作,每套服裝,武器,都只有一套,而且是獨(dú)立的。引擎可以根據(jù)不同的需要,臨時(shí)將幾組圖像拼裝到一起,進(jìn)而形成變化豐富的角色外觀。例如同時(shí)角色奔跑,可以在手部繪制武器A,也可以繪制武器B。 為了豐富角色的動(dòng)作,2D紙娃娃有時(shí)也將角色的頭,身,手,腳等部位的動(dòng)作都分開(kāi)繪制,在2D圖像基礎(chǔ)上展示了更多變的角色動(dòng)作。 2D紙娃娃系統(tǒng)比起普通游戲的最大優(yōu)勢(shì)就在于,數(shù)量相同的角色外觀下,占用更少的資源,角色的外觀變化即時(shí)展示。而這樣的系統(tǒng)在編程稍稍復(fù)雜。
紙娃娃系統(tǒng)并不復(fù)雜,它的難度如以下這個(gè)問(wèn)題。
桌子上有一個(gè)碗,碗里面有個(gè)杯子,移動(dòng)了一下桌子,問(wèn)杯子的坐標(biāo)? ?(已知桌子的坐標(biāo),已知碗在桌子中的坐標(biāo))。
為了實(shí)現(xiàn)紙娃娃這種嵌套系統(tǒng),我們需要引入相對(duì)坐標(biāo)和絕對(duì)坐標(biāo)的概念。
上回說(shuō)的接口扮演者Act 和類演員Actor,我們添加新方法
/**獲得絕對(duì)坐標(biāo)X*/public double getAbsoluteX();/**獲得絕對(duì)坐標(biāo)Y*/public double getAbsoluteY();/**獲得相對(duì)于容器坐標(biāo)X*/public double getX() ;/**設(shè)置相對(duì)于容器坐標(biāo)X*/public void setX(double x);/**獲得相對(duì)于容器坐標(biāo)Y*/public double getY();/**設(shè)置相對(duì)于容器坐標(biāo)Y*/public void setY(double y)//獲得絕對(duì)坐標(biāo)方法
public double getAbsoluteX() {//如果容器不為空, 絕對(duì)坐標(biāo)X=容器的絕對(duì)坐標(biāo)X加相對(duì)坐標(biāo)Xreturn getActParent()== null ? getX() : getActParent().getAbsoluteX() + getX();}public double getAbsoluteY() {//如果容器不為空, 絕對(duì)坐標(biāo)Y=容器的絕對(duì)坐標(biāo)Y加相對(duì)坐標(biāo)Yreturn getActParent() == null ? getY() : getActParent().getAbsoluteY() + getY();}繪制內(nèi)部子扮演者方法
/** 繪制當(dāng)前 */public void draw(GameCanvas canvas, IAct thisAct) {if (getModel() != null)getModel().draw(canvas, thisAct);drawChild(canvas);};//繪制子扮演者public void drawChild(GameCanvas canvas) {if (childList != null) {Iterator<IAct> it = childList.iterator();while (it.hasNext()) {IAct act = it.next();act.draw(canvas, act);if (act.getScript() != null)act.getScript().timeScript(act.getGameStage(), canvas, act);}}}package game.engines.inteface;import java.util.HashMap;import game.engines.Direction; import game.engines.GameCanvas; import game.engines.GameStage; import game.engines.Model; import game.engines.Script;/*** 扮演者*/ public interface IAct {/**將本身作為容器添加扮演者 被添加的扮演者絕對(duì)坐標(biāo)將以容器相對(duì)坐標(biāo)來(lái)計(jì)算*/public void addAct(IAct act);/**移除扮演者*/public void removeAct(IAct act);/**獲得該扮演者上層容器*/public IAct getActParent();/**獲得該扮演者上層容器*/public void setActParent(IAct act);/**繪制該版本扮演者* 該方法同時(shí)* @see drawChild* */public void draw(GameCanvas canvas,IAct act);/**繪制扮演者容器中的子扮演者*/public void drawChild(GameCanvas canvas);/**設(shè)置扮演者腳本*/public void setScript(Script script);/**獲得扮演者腳本*/public Script getScript();/**獲得扮演者腳本*/public HashMap<String,Object> getAttributes();/**獲得設(shè)置屬性集*/public void setAttributes(HashMap<String, Object> attributes);/**獲得設(shè)置屬性*/public void setAttributes(String key,Object value);/**獲得絕對(duì)坐標(biāo)X*/public double getAbsoluteX();/**獲得絕對(duì)坐標(biāo)Y*/public double getAbsoluteY();/**獲得相對(duì)于容器坐標(biāo)X*/public double getX() ;/**設(shè)置相對(duì)于容器坐標(biāo)X*/public void setX(double x);/**獲得相對(duì)于容器坐標(biāo)Y*/public double getY();/**設(shè)置相對(duì)于容器坐標(biāo)Y*/public void setY(double y);/**獲得寬度屬性*/public int getWidth();/**設(shè)置寬度屬性*/public void setWidth(int width) ;/**獲得高度屬性*/public int getHeight();/**設(shè)置高度屬性*/public void setHeight(int height);/**獲得移動(dòng)速度*/public double getMove();/**設(shè)置移動(dòng)速度*/public void setMove(double move);/**獲得造型*/public Model getModel();/**設(shè)置造型*/public void setModel(Model model);/**設(shè)置方向*/public void setDirection(Direction direction);/**獲得方向*/public Direction getDirection();/**獲得所在舞臺(tái)*/public GameStage getGameStage();/**設(shè)置所在舞臺(tái)*/public void setGameStage(GameStage stage);}
利用紙娃娃系統(tǒng)來(lái)編寫的太陽(yáng)系。如圖 太陽(yáng)(黃色) 地球(青色) ?月球(藍(lán)色) 衛(wèi)星(灰色)?
如果將太陽(yáng)系看作為一個(gè)整體你可以想象這用java需要多少行代碼。
實(shí)際上只需要很少量的代碼就足以完成它。
代碼示例
package game.demo;import android.graphics.Color; import game.engines.Actor; import game.engines.GameCanvas; import game.engines.GameStage; import game.engines.Model; import game.engines.Script; import game.engines.action.CircleMoveScript;import game.engines.inteface.IAct;/*** 游戲劇情腳本*/ public class MyGameScript extends Script {/*** 時(shí)間腳本* */public void timeScript(GameStage stage, GameCanvas canvas, IAct act) {//新建一只精靈Actor sun= new Actor();//新建一個(gè)造型.Model circle = new Model() {@Overridepublic void draw(GameCanvas canvas, IAct thisAct) {try {//獲得顏色屬性int color = (Integer) thisAct.getAttributes().get("Color");canvas.getPaint().setColor(color);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}// paint.setStyle(Paint.Style.STROKE);//在絕對(duì)坐標(biāo)上繪制一個(gè)圓canvas.drawCircle(thisAct.getAbsoluteX(),thisAct.getAbsoluteY(), thisAct.getHeight(),canvas.getPaint());}};//設(shè)置太陽(yáng)的造型是圓sun.setModel(circle);//設(shè)置太陽(yáng)的屬性 Color 黃色sun.setAttributes("Color", Color.YELLOW);sun.setX(250);sun.setY(150);sun.setWidth(25);sun.setHeight(25);//設(shè)置腳本為圓運(yùn)動(dòng) 半徑25 角度從100開(kāi)始 速率10毫秒內(nèi)0.005轉(zhuǎn)sun.setScript(new CircleMoveScript(25, 100, 0.005));//新建地球Actor earth = new Actor();earth.setAttributes("Color", Color.CYAN);earth.setModel(circle);earth.setWidth(15);earth.setHeight(15);earth.setScript(new CircleMoveScript(130, 0, 0.01));//Actor moon = new Actor();moon.setAttributes("Color", Color.BLUE);moon.setModel(circle);moon.setWidth(5);moon.setHeight(5);moon.setScript(new CircleMoveScript(35, 0, 0.04));Actor star = new Actor();star.setAttributes("Color", Color.GRAY);star.setModel(circle);star.setWidth(2);star.setHeight(2);star.setScript(new CircleMoveScript(10, 0, 0.1));//將月亮和衛(wèi)星組合一個(gè)系統(tǒng)moon.addAct(star);//將地球和月亮組合一個(gè)系統(tǒng)earth.addAct(moon);//將太陽(yáng)和地球組合一個(gè)系統(tǒng)sun.addAct(earth);// 獲得腳本的扮演者當(dāng)前的舞臺(tái)的場(chǎng)景 添加扮演者act.getGameStage().getScreen().addAct(sun);// 因?yàn)檫@個(gè)腳本只需要執(zhí)行一次 所以執(zhí)行完移除腳本act.getGameStage().setScript(null);}
*這時(shí)會(huì)發(fā)現(xiàn)Actor本身能代替Layer畫布的功能,所以Layer可以刪除今后由Actor任意實(shí)現(xiàn)多層嵌套紙娃娃系統(tǒng)的功能。
腳本引擎本身也是可以嵌套,重用性很強(qiáng)。我們的開(kāi)發(fā)工作會(huì)越來(lái)越輕松。足夠的靈活將帶給我們所需要的強(qiáng)大的功能。
舉個(gè)例子將來(lái)我們可以實(shí)現(xiàn)配置文件,
比如飛機(jī)墜落腳本,你能想象它的運(yùn)動(dòng)方式
飛機(jī)墜落.txt
[飛機(jī)]
x=0
y=0
width=100
height=100
script=圓周運(yùn)動(dòng),向右運(yùn)動(dòng),向下運(yùn)動(dòng)
總結(jié)
以上是生活随笔為你收集整理的android 2D游戏开发,引擎设计(三) 实验脚本编写与纸娃娃系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: VC 6中使用不同调用规范的函数在符号文
- 下一篇: 视频参数(流媒体系统,封装格式,视频编码