想了解更多内容,鸿蒙请访问:
和华为官方合作共建的开源框架鸿蒙技术社区
https://harmonyos.51cto.com
本项目是基于开源项目JustWeEngine进行ohos化的移植和开发的,可以通过项目标签以及github地址(https://github.com/lfkdsk/JustWeEngine )追踪到原项目版本
方法1.
编译har包JustWeEngine.har。 启动 DevEco Studio,鸿蒙将编译的开源框架har包,导入工程目录“entry->libs”下。第方 在moudle级别下的组件build.gradle文件中添加依赖,在dependences标签中增加对libs目录下har包的游戏引用。 dependencies { implementation fileTree(dir: libs,鸿蒙 include: [*.jar, *.har]) …… }4.在导入的har包上点击右键,选择“Add as Library”对包进行引用,开源框架选择需要引用的第方模块,并点击“OK”即引用成功。组件
方法2.
1.在工程的游戏build.gradle的allprojects中,添加HAR所在的Maven仓地址(等maven发布后进行修改)
repositories { maven { url https://s01.oss.sonatype.org/content/repositories/releases/ } }2.在应用模块的云南idc服务商build.gradle的dependencies闭包中,添加如下代码:(等maven发布后进行修改)
dependencies { implementation io.github.dzsf:just-we-engine:1.0.1 }使用说明
1.基础功能
1.1继承引擎核心类 1.2绘制文字 1.3绘制图片 1.4使用精灵 1.5使用按钮2.动画系统
2.1绑定在BaseSub物品及精灵基类上的动画类 2.2绑定在Button上的动画类3.物体分组碰撞检测和死亡判定
4.屏幕扫描模式
5.工具类
6.音频系统
6.1播放短音效 6.2播放音频 6.3通过短音效编曲7.使用网络
8.使用状态机精灵
9.CrashHandler崩溃守护
10.使用蓝牙
10.1开启、关闭服务 10.2扫描设备 10.3发送消息11.SQLite数据库
11.1创建表 11.2增删查改由于框架全部使用SurfaceView进行绘制,不使用诸如Button、Layout等原生控件,所以应该首先新建类继承引擎核心类Engine,负责游戏的流程,注释中已有明确的标明功能。
public class MainAbility extends Engine implements Runnable, Component.TouchEventListener, Component.DrawTask { // 一般在构造函数完成变量的初始化 public MainAbility() { } public void onStart(Intent intent) { // 调用初始化方法 init(); } // 载入一些UI参数和设置屏幕放向,默认背景色,设定屏幕的扫描方式等 public void init() { // 初始化UI默认参数,必须调用该方法,其中有一些用于多机型适配的参数需要初始化 UIdefaultData.init(this); } // 通常用于精灵,背景,图片等物体的设置和载入 public void load() { } // draw 和 update 在线程中进行不断的循环刷新 // draw 负责绘制 update 负责更新数据和对象信息 public void draw() { } public void update() { } // 将touch 事件传回 功能和所设定的屏幕扫描方式有关 public void touch(TouchEvent event) { } // 将碰撞事件传回 传回精灵和物品的基类 // 用于处理碰撞事件 默认使用矩形碰撞 public void collision(BaseSub baseSub) { } }使用GamePrinter进行文字绘制,除此以外还有多种方法绘制:
@Override public void draw() { Canvas canvas = getCanvas(); GameTextPrinter printer = new GameTextPrinter(canvas); printer.drawText("哈哈哈", 100, 100); }建议图片存放在Resources中:
GameTexture texture = new GameTexture(this); texture.loadFromAsset("resources/base/graphic/shoot.png") texture.draw(canvas, 100, 100);另外也可使用loadFromAssetStripFrame从一个大的图片中取出对应位置的图片。
/** * get bitmap from a big bitmap * * @param filename * @param x * @param y * @param width * @param height * @return */ public boolean loadFromAssetStripFrame(String filename, int x, int y,PicUtils中提供了在Bitmap处理中很有用的各种特效和压缩方法,大家可以一试。
使用精灵可以使用BaseSprite也可以继承该类使用,亿华云BaseSprite封装了很多方法供各种动画使用,这些功能很多都是需要结合动画系统来使用的,动画系统会在后面介绍。
新建精灵:
连续帧的初始化需要连续的帧图片。
GameTexture texture = new GameTexture(this); texture.loadFromAsset("resources/base/graphic/flare.png"); // 长宽以及列数 sprite = new BaseSprite(this, 96, 96, 8); sprite.setTexture(texture); sprite.setPosition(100, 100); sprite.setDipScale(100, 100); // 帧切换动画是关键 sprite.addAnimation(new FrameAnimation(0, 63, 1)); addToSpriteGroup(sprite);使用的按钮可以继承BaseButton进行拓展,也可以直接使用TextureButton和TextButton进行使用。
Button设定功能的方式和原生一样,通过设定接口回调的方式进行:
button.setOnClickListener(new OnClickListener() { @Override public void onClick() { Log.e("button", "onClick"); } });TextureButton button; // 初始化并设定名字 button = new TextureButton(this, "logo"); texture = new GameTexture(this); texture.loadFromAsset("resources/base/graphic/logo.jpg"); // 添加图片资源 button.setTexture(texture); // button的接口回调,不是View的那个接口 button.setOnClickListener(new OnClickListener() { @Override public void onClick() { Log.e("button", "onClick"); } }); button.setPosition(200, 300); button.setDipScale(100, 150); // 添加到ButtonGroup进行绘制和处理 addToButtonGroup(button);
结合PicUtil中的各种Bitmap处理方法可以很容易的做出各种样式的Button。
TextButton button;
TextButton button; button = new TextButton(this, "logo"); button.setText("刘丰恺"); addToButtonGroup(button); // 余略见源码 ...
目前的动画系统可以使用已经封装好的继承了BaseAnimation的动画,也可以继承BaseAnim进行自我定义动画类进行使用。
绑定在BaseSub物品及精灵基类上的亿华云计算动画类
AnimType中保存了Animation的应用类型。
绑定动画分为两类,ListAnimation和FixedAnimation,ListAnimation将动画存储到固定的一个List中,用于重复更新的动画,
而FixedAnimation存储在Map中,使用名字进行调用,用于点击或者非自动更新的动画。
比如前面精灵类动画的就是添加到ListAnimation。
下面的这种写法就是FixedAnimation,这个动画是飞机入场,因为只使用了一次,所以使用了FixedAnimation。
ship.addfixedAnimation("start", new MoveAnimation(UIdefaultData.centerInHorizontalX - ship.getWidthWithScale() / 2, UIdefaultData.screenHeight - 2 * ship.getHeightWidthScale(), new Float2(10, 10)));绑定在Button上的动画类
BaseButtonAnimation是BaseButton的动画类继承了BaseAnim的动画基类,通过提供Button的状态,设定Button的动画。
为Button设定放缩动画:
// 设定中心放缩 button.setZoomCenter(true); // 三个参数 初始值/放大值/帧数 button.setAnimation(new ZoomCenterButtonAnim(10, 30, 3));为Button设定颜色动画:
// 初始颜色 / 按下颜色 button.setAnimation( new ColorAnimation(UIdefaultData.colorAccent, UIdefaultData.colorPressed));使用设置ID和Name进行物体分组,通过物体分组,框架核心类会对对象进行分类处理。
final int SHIP = 0; ship.setName("SHIP"); ship.setIdentifier(SHIP);只要使用了addToSpriteGroup(sprite)的精灵对象就会自动进行碰撞检测,而对碰撞检测的结果会从
collision中进行发回。
@Override public void collision(BaseSub baseSub) { // 获取与之碰撞的对象 BaseSprite other = (BaseSprite) baseSub.getOffender(); // 获取ID分组处理 if (baseSub.getIdentifier() == BULLET && other.getIdentifier() == ENEMY) { // 设定死亡 other.setAlive(false); // 回收 removeFromSpriteGroup(other); addToRecycleGroup(other); } }其中getOffender()获得与之碰撞的对象,通过getIdentifier()获取设定的对象分组,实行逻辑判断。
开启Debug模式会看见碰撞线。
屏幕扫描模式是用来优先响应屏幕点击、Button点击、和多点触控而设的,放置在不同情况下都能优化屏幕的刷新。
// 检测单一移动 SINGLE, // 检测Button BUTTON, // 多点检测 FULL, // 单击+Button SINGLE_BUTTON并且通过如下方式进行设置:
super.setTouchMode(TouchMode.BUTTON);播放短音效
播放短音效,首先初始化SoundManager用以加载音效。
// 接收实例和Manager的尺寸 SoundManager manager = new SoundManager(this, 5); // 从assets加载音频 同时加载路径也会作为音效名进行存储 manager.addSound("resource/rawfile/open.mid"); // 通过加载名进行播放 manager.play("resource/rawfile/open.mid");完成以上步骤就可以播放了,当然尽量只向其中放置较短的音效,如背景音乐的长音频,请见播放音频。
public void removeSound(String musicName) // 移除 public void play(String musicName, float volume) // 播放 + 音量 public boolean containSoundID(int soundID) // 判断音频是否存在 public int getSoundID(String soundName) // 获取ID ...播放音频
播放音频适合例如背景音乐一样的音乐。
// 传入两个参数 上下文和文件名 MusicPlayer player = new MusicPlayer(this, "resources/rawfile/open.mp3"); player.play();以上的就能实现播放了,下面还有一些其他的方法。
public void dispose() // 清理 public void setLooping(boolean isLooping) // 是否循环 public void setVolume(float volume) // 设定音量 ...通过短音效编曲
从SoundManager中导入多段音频,快速播放达成音效的效果。
SoundManager manager = new SoundManager(this, 5); manager.addSound("resources/rawfile/media/1.mid"); manager.addSound("resources/rawfile/media/2.mid"); SoundPlayer player = new SoundPlayer(manager, 500, 16); player.addSound("resources/rawfile/media/1.mid"); player.addSound("resources/rawfile/media/2.mid"); ...
使用player.play();进行播放。
网络的使用可参考JustWe-WebServer中的介绍。
按照介绍操作就可以通过:
server.apply("/lfk", new OnWebStringResult() { @Override public String OnResult() { return "======="; } }); server.apply("/main", new OnWebFileResult() { @Override public File returnFile() { return new File(WebServerDefault.WebServerFiles+"/"+"welcome.html"); } });
这样的简单方式绑定路由,而get/post数据可以直接使用http协议的get和post进行。
可以通过上述的addState方法为状态机精灵添加一个任务,只有当第一个参数接口回调的返回值为真的时候,
才会去运行第二个参数提供的指令,如果返回为假则会运行第二项状态的判断。
状态的优先级由加入顺序提供。
CrashHandler用于处理游戏的意外崩溃事件,初始化推荐在Application中进行。
CrashHandler可以自动保存机型和异常日志,以便让开发者找到问题所在。
CrashHandler.getInstance().init(this);使用以上语句即可自动保存错误日志。
还可以:
CrashHandler.getInstance().setRestartActivity(MainActivity.class); // 重启的Activity // 添加崩溃回调 CrashHandler.getInstance().addCrashListener(new AfterCrashListener() { @Override public void AfterCrash() { // 设定保存项目 ... } });开启、关闭服务
使用蓝牙需要新建BlueToothServer对象,传入上下文和MessageBack接口。
blueToothServer = new BlueToothServer(this, new OnMessageBack() { @Override public void getMessage(String msg) { Log.e("L", msg); } @Override public void sendMessage(String msg) { Log.e("L", msg); } @Override public void getDevice(ArrayList<String> msg) { Log.e("L", msg.size() + ""); } }); // 使用如下语句进行初始化 blueToothServer.init();服务初始化之后如未打开蓝牙,系统会自动提示应用要求蓝牙开启。
通过MessageBack接口可以接收到发送、接收、以及扫描设备信息,采取对应操作就可以获得数据。
关闭服务时请使用blueToothServer.unBindService();关闭服务。
扫描设备
使用blueToothServer.doDiscovery();进行设备扫描,返回结果在OnMessageBack()接口的
getDevice()方法接收。
使用blueToothServer.ensureDiscoverable();允许被扫描。
使用blueToothServer.getPairedDevices();返回已配对的设备列表。
发送消息
在配对成功之后就可以使用blueToothServer.sendMessage(String msg);发送消息了。
同时,消息的接收也可以从getMessage()接口中获得。
SQLite使用了IOC的模式。
创建表
新建的创建表需要继承Node并且写出注解类。
// 表名 @TableName(tableName = "lfkdsk") public class User extends Node { // 主键自增 INTEGER型 @LabelName(autoincrement = true, type = LabelName.Type.INTEGER, columnName = "name", generatedId = true) private int name; // TEXT型 栏名为user_name @LabelName(type = LabelName.Type.TEXT, columnName = "user_name") private String user_name; // 自增主键所以只需要提供其他信息 public User(String user_name) { super(user_name); this.user_name = user_name; } public User(int name, String user_name) { super(name, user_name); this.name = name; this.user_name = user_name; } public int getName() { return name; } public void setName(int name) { this.name = name; } public String getUser_name() { return user_name; } public void setUser_name(String user_name) { this.user_name = user_name; } } // 通过这种方式获取数据库 表名 private DataBase dataBase = DataBase.initAndOpen("user", User.class);增删查改
// add database.insert(User user); // find database.get(int position); // delete database.delete(int position); // update database.update(User user); ...项目地址:https://gitee.com/openneusoft/just-we-engine
IDE官方下载地址:https://developer.harmonyos.com/cn/develop/deveco-studio
想了解更多内容,请访问:
和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com