如何使用libgdx编写一个简单的游戏(三)— 人性化

长平狐 发布于 2013/11/25 11:37
阅读 1K+
收藏 0

这一篇主要是添加一些让游戏更人性化的东西,比如音效和加载画面,菜单等等。

这其中用到了很多资源,主要出自以下几个网站,大家有需要也可以去上面寻找。

http://www.freesound.org/

添加音效

首先是飞镖发出时候的音效,我希望是类似"bing"的一声,要短小精炼。

我使用的是http://www.freesound.org/people/BMacZero/sounds/96132/

libgdx支持的音频主要是WAV, MP3和OGG,其他的支持需要扩展支持。

libgdx中的音频有两种,一种是sound,一种是music。

一般所谓的音效使用sound,而音乐就使用music。

在DartController中添加属性

Sound bing;

在实例化方法中添加

this.bing = Gdx.audio.newSound(Gdx.files.internal("audio/bing.wav"));

在AddDart方法中添加

bing.play();

 

在怪兽被消灭的时候的音效我选用http://www.freesound.org/people/yottasounds/sounds/174465/

在TargetController中添加

great = Gdx.audio.newSound(Gdx.files.internal("audio/great.wav"));

最后添加一个背景音乐。我使用的是http://www.freesound.org/people/Setuniman/sounds/167453/

大小为5.7M,个人感觉有点大。

而且我需要循环播放,这就意味着末尾的这个部分的我不需要。

01

使用在线转换器截取并转化成ogg。

02

转化以后大小变成465kb了。仔细听一下,感觉很多部分是重复,所以再一次截取,只要前4秒的。

转化好以后在主类添加

backgroundMusic = Gdx.audio.newMusic(Gdx.files
		.internal("audio/background.ogg"));
backgroundMusic.setLooping(true); //循环播放
backgroundMusic.setVolume(0.4f); //设置音量
backgroundMusic.play(); //播放

因为music可以在resume和pause时自动播放和暂停,所以不需要其他的处理。在游戏关闭时需要将其释放掉。

backgroundMusic.dispose();

Game-Screen模式和资源预加载

到目前为止我们的所有操作都在一个界面上,但是一个游戏中可能有很多不同的界面和场景,比如菜单,帮助,关卡1,关卡2等等。

libgdx提供了Game-Screen模式,即只有一个Game,但是Game中有很多Screen。通过setScreen来切换。

这里注意一下Game所提供的切换功能没有任何过渡效果,后面会有添加过多效果的例子。

新建DartsGame类,继承Game类。在darts-shasha-android项目和darts-shasha-desktop项目中分别修改入口代码

package com.cnblogs.htynkn;

import android.os.Bundle;

import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;

public class MainActivity extends AndroidApplication {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
        cfg.useGL20 = false;
        
        initialize(new DartsGame(), cfg);
    }
}

package com.cnblogs.htynkn;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;

public class Main {
	public static void main(String[] args) {
		LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
		cfg.title = "darts-shasha";
		cfg.useGL20 = false;

		cfg.width = 480;
		cfg.height = 320;
		
		new LwjglApplication(new DartsGame(), cfg);
	}
}

新建一个类ShaScreen,实现Screen接口,其中的代码基本和原来的主类一样。唯一的区别就是create中的代码需要移动到show中。

在DartsGame中添加代码

package com.cnblogs.htynkn;

import com.badlogic.gdx.Game;
import com.cnblogs.htynkn.screen.ShaScreen;

public class DartsGame extends Game {
	@Override
	public void create() {
		ShaScreen screen = new ShaScreen();
		this.setScreen(screen);
	}
}

这样我们就转化到Game-Screen模式。

当我们在游戏中使用了很多资源的时候直接new的话经常会卡顿,比如我们这个demo再加入音效后进入时间明显变长了。

所以我们这里需要一个预加载过程,而libgdx提供的AssetManager可以实现这个功能。

加载中使用一个小图标加文字形式。由于要使用中文,同时文字量很小,所以使用hiero作图。

03

新建一个LoadingScreen类作为加载页面。

因为AssetManager的作用很特殊,很多类都可以要调用它,所以我一般使用单例模式。

在DartsGame添加

public static AssetManager manager;
public static AssetManager getManager() {
	if (manager == null) {
		manager = new AssetManager();
	}
	return manager;
}

在LoadingScreen中通过

AssetManager manager = DartsGame.getManager();

获取manager。然后通过load方法添加要加载的资源

manager.load("audio/background.ogg", Music.class);
manager.load("audio/bing.wav", Sound.class);
manager.load("audio/great.wav", Sound.class);
manager.load("pack/sha/default.pack", TextureAtlas.class);

这里只是告诉manager要加载什么资源,并没有实际加载。

在render方法中调用

DartsGame.getManager().update()

来启动加载并获取是否加载完成,如果返回值为true那么就表明加载完成。

其他类通过

DartsGame.getManager().get()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

来获取资源。

LoadingScreen代码如下:

package com.cnblogs.htynkn.screen;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
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.cnblogs.htynkn.DartsGame;

public class LoadingScreen implements Screen {

	Game game;
	Stage stage;

	@Override
	public void render(float delta) {
		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		if (DartsGame.getManager().update()) {
			game.setScreen(new ShaScreen());
		}
		stage.act();
		stage.draw();
	}

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

	}

	@Override
	public void show() {
		AssetManager manager = DartsGame.getManager();
		manager.load("audio/background.ogg", Music.class);
		manager.load("audio/bing.wav", Sound.class);
		manager.load("audio/great.wav", Sound.class);
		manager.load("pack/sha/default.pack", TextureAtlas.class);

		stage = new Stage(480, 320, true);
		BitmapFont font = new BitmapFont(
				Gdx.files.internal("pack/loading/font.fnt"), false);
		LabelStyle labelStyle = new LabelStyle(font, Color.WHITE);
		Label label = new Label("游戏加载中...", labelStyle);
		label.setPosition(160, 150);
		stage.addActor(label);
		Image image = new Image(
				new TextureAtlas(Gdx.files
						.internal("pack/loading/default.pack"))
						.findRegion("ninja_attack"));
		image.setOrigin(image.getWidth() / 2, image.getHeight() / 2);
		image.addAction(Actions.repeat(1000, Actions.rotateBy(360, 3f)));
		image.setPosition(100, 140);
		stage.addActor(image);
	}

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

	}

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

	}

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

	}

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

	}

	public LoadingScreen(Game game) {
		this.game = game;
	}
}

 

效果如下:

04

当我们不需要某个资源时通过

manager.unload

来销毁。或者使用

manager.clear();

来清空所有资源。

添加友盟统计

统计功能对于一个应用是必须的。你可以获取到用户的信息,比如分辨率,系统版本,还可以快速获取到错误等等。

libgdx是一个游戏框架,没有自带的统计功能,这里我选用友盟统计。

首先申请key

06

申请完成以后获取Appkey并下载SDK,拷贝到android项目的libs文件夹中。

在AndroidManifest.xml中添加相关信息

 
 

 

详细的情况参考友盟的文档。

现在来看一下友盟文档,最常用的是

MobclickAgent.onResume(this);
MobclickAgent.onPause(this);

为了方便开发,我们新建一个接口IStatisticsService。

package com.cnblogs.htynkn.extension;

public interface IStatisticsService {
	void onResume();
	void onPause();
}

 

然后在DartsGame类添加

public static IStatisticsService statisticsService;

 

然后在Android项目中添加AndroidStatisticsService

package com.cnblogs.htynkn.extension;

import android.content.Context;

import com.umeng.analytics.MobclickAgent;

public class AndroidStatisticsService implements IStatisticsService {

	Context context;

	public AndroidStatisticsService(Context context) {
		this.context = context;
	}

	@Override
	public void onResume() {
		MobclickAgent.onResume(context);
	}

	@Override
	public void onPause() {
		MobclickAgent.onPause(context);
	}

}

 

修改入口文件为

package com.cnblogs.htynkn;

import android.os.Bundle;

import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.cnblogs.htynkn.extension.AndroidStatisticsService;

public class MainActivity extends AndroidApplication {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
		cfg.useGL20 = false;
		DartsGame dartsGame = new DartsGame();
		DartsGame.setStatisticsService(new AndroidStatisticsService(this));
		initialize(dartsGame, cfg);
	}
}

 

同样的,在桌面项目中添加DesktopStatisticsService

package com.cnblogs.htynkn.extension;

import com.badlogic.gdx.Gdx;

public class DesktopStatisticsService implements IStatisticsService{

	@Override
	public void onResume() {
		Gdx.app.log("StatisticsService", "onResume");
	}

	@Override
	public void onPause() {
		Gdx.app.log("StatisticsService", "onPause");
	}

}

修改入口文件

package com.cnblogs.htynkn;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.cnblogs.htynkn.extension.DesktopStatisticsService;

public class Main {
	public static void main(String[] args) {
		LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
		cfg.title = "飞镖杀杀";
		cfg.useGL20 = false;
		cfg.width = 480;
		cfg.height = 320;
		DartsGame.setStatisticsService(new DesktopStatisticsService());
		new LwjglApplication(new DartsGame(), cfg);
	}
}

因为桌面项目并没有统计功能,所以以输出log替代。

然后在游戏相应位置调用即可。

其他需要的功能办法基本相同,就是实现相应接口,然后不同的平台传入不同实现。没有实现的就用mock输出。

依照这种方法还可以添加其他第三方功能。

不过很遗憾友盟SDK升级以后我死活用不上了…现在换成百度APP统计了。原理是一样的,具体参考源码。

比如在Android的启动文件中重写onPause和onResume

package com.cnblogs.htynkn;

import android.os.Bundle;

import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.cnblogs.htynkn.extension.AndroidStatisticsService;

public class MainActivity extends AndroidApplication {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
		cfg.useGL20 = false;
		DartsGame dartsGame = new DartsGame();
		DartsGame.setStatisticsService(new AndroidStatisticsService(this));
		initialize(dartsGame, cfg);
	}

	@Override
	protected void onResume() {
		super.onResume();
		DartsGame.getStatisticsService().onResume();
	}

	@Override
	protected void onPause() {
		super.onPause();
		DartsGame.getStatisticsService().onPause();
	}
}

统计结果

09 

10
我还实现了其他方法,比如事件记录等等。

11

说实话,友盟的统计比百度的好很多,但是不知为嘛我用不起了。

写在最后

本来这一篇写好很久了,但是我一直想加入一个菜单和游戏结束的界面,不过最近实在没有时间,先发出来这个部分吧。

如果有时间以后会补上的。

Github仓库地址:https://github.com/htynkn/DartsShaSha 对应的tag是page3。

apk下载地址:http://pan.baidu.com/share/link?shareid=385272&uk=4127624209


原文链接:http://www.cnblogs.com/htynkn/archive/2013/03/17/libgdx-game-3.html
加载中
0
山东-小木
山东-小木
这是少量使用中文的情况,请问如果是像游戏中的一些任务说明或者聊天信息这种中文怎么处理呢?
返回顶部
顶部