天天看點

android遊戲開發架構libgdx的使用(十九)—使用自定義配置改進AVG遊戲開發libgdx的工具庫配置檔案格式分析使用libgdx實作相關效果

本文使用的libgdx是0.92版本,和現在的最新版可能有一些不一樣的地方。全文内容僅供參考。

先說明一下上一篇文章我使用了多張hiero圖的字型繪制,因為我對源碼進行了一些修改,本來想這次發出來的,但是我仔細調試了一下,發現對于多圖的支援還是有問題,有些字會出現偏移。

這個隻有繼續嘗試了…大家可以考慮使用ttf字庫。

然後繼續說上一篇,雖然實作了一個簡單的效果,但是目前有很多不足。我把AVG遊戲需要的資源全部提取出來,放在一個個檔案夾中,然後通過配置檔案加載這些資料。

libgdx的工具庫

com.badlogic.gdx.utils就是libgdx的工具庫,支援兩種格式xml和json。

我最先傾向于使用json格式,但是反複想了想,雖然json的大小可能要小點,但是沒有xml直覺好讀。

是以還是選擇使用xml格式,讀取xml檔案使用XmlReader。

XmlReader reader=new XmlReader(); 
try { 
    Element config=reader.parse(Gdx.files.internal("data/config.xml")); 
    config.get("name"); //擷取屬性值,如果沒有屬性值則傳回同名child的值 
    config.getAttribute("name"); //擷取屬性值 
} catch (IOException e) { 
    e.printStackTrace(); 
}       

配置檔案格式分析

配置檔案需要配置的内容其實就是上一篇我們寫死進去的東西,有背景、邊框、對話等。

我設計的比較随意,不一定是最好的,大家可以參考參考。

<?xml version="1.0" encoding="UTF-8"?> 
<scene> 
<packfile>pack</packfile> 
<background>bg1</background> 
<border> 
<border-name>border</border-name> 
<border-left>26</border-left> 
<border-right>26</border-right> 
<border-top>31</border-top> 
<border-bottom>31</border-bottom> 
</border> 
<dialogues> 
<dialogue> 
<name>人物1</name> 
<data>這是對話1</data> 
</dialogue> 
<dialogue> 
<name>人物1</name> 
<data>這是對話2</data> 
</dialogue> 
</dialogues> 
</scene>      

如果對話比較長還可以繼續添加<dialogue>節點。border-*那4個值就是NinePatch的左邊距、右邊距、上邊距、下邊距。

這裡還有一個地方需要注意,如果我們需要切換場景怎麼辦?切換的場景可能是一個AVG場景,也可能是個一般的Screen。我本來想做個簡單的IOC容器的,但後來想想也沒有那麼複雜。

在配置檔案中加上一句

如果是一般Screen就是

<nextscreen type="standard">com.cnblogs.htynkn.screen.GameOver</nextscreen>      

如果是AVG場景就是

<nextscreen type="avg">data/scene2/config.xml</nextscreen>      

使用libgdx實作相關效果

其實整個原理和上一篇原理是一樣的,唯一多的一個就是解析配置檔案和場景跳轉。

XmlReader xmlReader = new XmlReader(); 
try { 
    Element config = xmlReader.parse(Gdx.files 
            .internal(this.configFileName)); //加載配置檔案 
    atlas = new TextureAtlas(Gdx.files.internal(configFileName) 
            .parent() 
            + "/" + config.get("packfile")); //擷取pack配置檔案 
    background = atlas.findRegion(config.get("background")); //建立背景圖 
    Element borderConfig = config.getChildByName("border"); //擷取border配置 
    border = new NinePatch(atlas.findRegion(borderConfig.getChild(0) 
            .getText()), Integer.parseInt(borderConfig.getChild(1) 
            .getText()), Integer.parseInt(borderConfig.getChild(2) 
            .getText()), Integer.parseInt(borderConfig.getChild(3) 
            .getText()), Integer.parseInt(borderConfig.getChild(4) 
            .getText())); //執行個體化border 
    dialogues = new ArrayList<String[]>(); 
    Element dialoguesConfig = config.getChildByName("dialogues"); //開始處理對話 
    for (int i = 0; i < dialoguesConfig.getChildCount(); i++) { 
        dialogues.add(new String[] { 
                dialoguesConfig.getChild(i).get("name"), 
                dialoguesConfig.getChild(i).get("data") }); 
    } 
    Element screenConfig = config.getChildByName("nextscreen"); //處理場景 
    if (screenConfig.getAttribute("type").equals("avg")) { 
        nextScreen = new AVGScreen(this.game, screenConfig.getText()); 
    } else { 
try { 
            nextScreen = (Screen) Class.forName(screenConfig.getText()) 
                    .newInstance(); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
    }

} catch (IOException e) { 
    e.printStackTrace(); 
}      

讀取完成後建構舞台,然後繪制。唯一需要修改的就是場景跳轉。

borderImage.setClickListener(new ClickListener() {

    @Override 
public void click(Actor actor, float x, float y) { 
if (currentSize < dialogues.size() - 1) { 
            currentSize++; 
        } else { 
if (nextScreen != null) { 
                game.setScreen(nextScreen); 
            } 
        } 
    } 
});       

完整代碼:

package com.cnblogs.htynkn.ui;

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List;

import com.badlogic.gdx.Game; 
import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.Screen; 
import com.badlogic.gdx.graphics.Color; 
import com.badlogic.gdx.graphics.GL10; 
import com.badlogic.gdx.graphics.Texture; 
import com.badlogic.gdx.graphics.g2d.BitmapFont; 
import com.badlogic.gdx.graphics.g2d.NinePatch; 
import com.badlogic.gdx.graphics.g2d.TextureAtlas; 
import com.badlogic.gdx.graphics.g2d.TextureRegion; 
import com.badlogic.gdx.scenes.scene2d.Actor; 
import com.badlogic.gdx.scenes.scene2d.Stage; 
import com.badlogic.gdx.scenes.scene2d.ui.ClickListener; 
import com.badlogic.gdx.scenes.scene2d.ui.Image; 
import com.badlogic.gdx.scenes.scene2d.ui.Label; 
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; 
import com.badlogic.gdx.utils.Array; 
import com.badlogic.gdx.utils.XmlReader; 
import com.badlogic.gdx.utils.XmlReader.Element;

public class AVGScreen implements Screen {

private String configFileName; 
private Stage stage; // 舞台 
    private List<String[]> dialogues; // 對話 
    private BitmapFont bitmapFont; // 文字 
    private NinePatch border; // 邊框 
    private int currentSize; // 目前對話序号 
    private TextureAtlas atlas; 
private TextureRegion background; 
private Screen nextScreen; 
private Game game;

public AVGScreen(Game game, String configFileName) { 
this.game = game;

        bitmapFont = new BitmapFont(Gdx.files.internal("font/chinese.fnt"), 
false);

this.configFileName = configFileName; 
        XmlReader xmlReader = new XmlReader(); 
try { 
            Element config = xmlReader.parse(Gdx.files 
                    .internal(this.configFileName)); 
            atlas = new TextureAtlas(Gdx.files.internal(configFileName) 
                    .parent() 
                    + "/" + config.get("packfile")); 
            background = atlas.findRegion(config.get("background")); 
            Element borderConfig = config.getChildByName("border"); 
            border = new NinePatch(atlas.findRegion(borderConfig.getChild(0) 
                    .getText()), Integer.parseInt(borderConfig.getChild(1) 
                    .getText()), Integer.parseInt(borderConfig.getChild(2) 
                    .getText()), Integer.parseInt(borderConfig.getChild(3) 
                    .getText()), Integer.parseInt(borderConfig.getChild(4) 
                    .getText())); 
            dialogues = new ArrayList<String[]>(); 
            Element dialoguesConfig = config.getChildByName("dialogues"); 
for (int i = 0; i < dialoguesConfig.getChildCount(); i++) { 
                dialogues.add(new String[] { 
                        dialoguesConfig.getChild(i).get("name"), 
                        dialoguesConfig.getChild(i).get("data") }); 
            } 
            Element screenConfig = config.getChildByName("nextscreen"); 
if (screenConfig.getAttribute("type").equals("avg")) { 
                nextScreen = new AVGScreen(this.game, screenConfig.getText()); 
            } else { 
try { 
                    nextScreen = (Screen) Class.forName(screenConfig.getText()) 
                            .newInstance(); 
                } catch (Exception e) { 
                    e.printStackTrace(); 
                } 
            }

        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
    }

    @Override 
public void dispose() { 
        bitmapFont.dispose(); 
        stage.dispose(); 
    }

    @Override 
public void hide() { 
// TODO Auto-generated method stub

    }

    @Override 
public void pause() { 
// TODO Auto-generated method stub

    }

    @Override 
public void render(float delta) { 
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        ((Label) stage.findActor("label")) 
                .setText(dialogues.get(currentSize)[0] + " : " 
                        + dialogues.get(currentSize)[1]);

        stage.act(Gdx.graphics.getDeltaTime()); 
        stage.draw(); 
    }

    @Override 
public void resize(int width, int height) { 
// TODO Auto-generated method stub

    }

    @Override 
public void resume() { 
// TODO Auto-generated method stub

    }

    @Override 
public void show() { 
        currentSize = 0;

        stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 
false); 
        Image backgroundImage = new Image(background); 
        backgroundImage.x = backgroundImage.y = 0; 
        backgroundImage.setFillParent(true);

        Image borderImage = new Image(border); 
        borderImage.x = borderImage.y = 0; 
        borderImage.width = Gdx.graphics.getWidth(); 
        borderImage.height = Gdx.graphics.getHeight() / 4; 
        borderImage.setClickListener(new ClickListener() {

            @Override 
public void click(Actor actor, float x, float y) { 
if (currentSize < dialogues.size() - 1) { 
                    currentSize++; 
                } else { 
if (nextScreen != null) { 
                        game.setScreen(nextScreen); 
                    } 
                } 
            } 
        });

        LabelStyle labelStyle = new LabelStyle(bitmapFont, Color.WHITE); 
        Label label = new Label("", labelStyle, "label"); 
        label.x = border.getLeftWidth() + 10; 
        label.y = borderImage.height - border.getTopHeight() - 10; 
        stage.addActor(backgroundImage); 
        stage.addActor(borderImage); 
        stage.addActor(label); 
        Gdx.input.setInputProcessor(stage); 
    } 
}       

最後貼上效果圖,這是我正在做的一個東西:

android遊戲開發架構libgdx的使用(十九)—使用自定義配置改進AVG遊戲開發libgdx的工具庫配置檔案格式分析使用libgdx實作相關效果
android遊戲開發架構libgdx的使用(十九)—使用自定義配置改進AVG遊戲開發libgdx的工具庫配置檔案格式分析使用libgdx實作相關效果