Flutter开放世界探索插件openworld的使用

Flutter开放世界探索插件openworld的使用

开源背景

此游戏引擎用Flutter编写,基于现有的threejs开放世界仓库openworldthreejs。该游戏引擎使用了three_dart包,使得从threejs代码到three_dart的转换变得简单。该包可在pub.dev上找到。由于它使用了Flutter,因此用此引擎创建的游戏可以在Android、iOS、Web、Windows和Linux平台上运行。此外,借助Flutter的热重载功能,可以实时将3D对象添加到场景中,从而简化游戏设计。

以下是一个小示例代码,展示了如何添加天空穹顶,但建议查看GitHub中的示例游戏以全面了解引擎的功能,包括天气、角色动画、地形、对话等。


导入库

import 'package:openworld_gl/openworld_gl.dart';
import 'package:openworld/three_dart/three3d/objects/index.dart';
import 'package:openworld/three_dart/three_dart.dart' as THREE;
import 'package:openworld/three_dart_jsm/three_dart_jsm.dart' as THREE_JSM;
import 'package:openworld/shaders/SkyShader.dart';
import 'package:openworld/openworld.dart' as OPENWORLD;

使用示例

添加天空穹顶

// 创建一个球形几何体作为天空穹顶
var skyGeo = THREE.SphereGeometry(-1000, 32, 15);

// 创建一个材质并应用天空着色器
var skyMat = new THREE.ShaderMaterial(SkyShader);

// 将几何体与材质组合为网格
var sky = THREE.Mesh(skyGeo, skyMat);

// 将天空网格添加到场景中
scene.add(sky);

// 设置天空材质的uniform参数
skyMat.uniforms = {
  'turbidity': {'value': 10.0},
  'reileigh': {'value': 2.0},
  'mieCoefficient': {'value': 0.005},
  'mieDirectionalG': {'value': 0.8},
  'luminance': {'value': 1.0},
  'inclination': {'value': 0},
  'azimuth': {'value': 0},
  'opacity': {'value': 1.0},
  'sunPosition': {'value': THREE.Vector3(0, 100, 0)}
};

// 添加太阳
var sunSphere = THREE.Mesh(THREE.SphereGeometry(20000, 16, 8),
    THREE.MeshBasicMaterial({'color': THREE.Color.fromHex(0xffffff)}));
sunSphere.position.y = -700000;
sunSphere.visible = true;
var sunlight = new THREE.SpotLight(0x888888);//ffffff);
sunlight.intensity = 0.4;
sunlight.penumbra = 1;
sunSphere.add(sunlight);

// 将太阳添加到场景中
scene.add(sunSphere);

// 初始化时间系统,根据太阳位置动态调整天空效果
OPENWORLD.Time.init(sunSphere, skyMat, ambience);

功能示例

添加动画角色

// 加载一个名为'weaponer'的角色模型,并共享另一个角色的动画
var weaponer = await OPENWORLD.Actor.createActor(
  'assets/actors/weaponer.glb',
  shareanimations: seller,
  action: 'idle',  // 角色开始时处于“idle”状态
  z: actoroffset,
);

// 设置角色的缩放比例
weaponer.scale.set(0.0025, 0.0025, 0.0025);

// 设置角色面向的方向(东)
OPENWORLD.Space.objTurn(weaponer, 90);

// 将角色放置在地形表面并设置隐藏逻辑(距离超过3单位时隐藏)
OPENWORLD.Space.worldToLocalSurfaceObjHide(
  weaponer, -0.12, 1.3, 0, 3);

// 将角色添加到场景中
scene.add(weaponer);

添加可交互的物体

// 加载一个模型并添加到场景中
var minorah = await OPENWORLD.Model.createModel('assets/models/minorah.glb');

// 设置模型的位置、缩放和可见性逻辑
OPENWORLD.Space.worldToLocalSurfaceObjHide(minorah, -0.33, 1.03, 0.0, 4);
minorah.scale.set(0.11, 0.11, 0.11);
OPENWORLD.Space.objTurn(minorah, 0);

// 设置触摸触发器
OPENWORLD.BaseObject.setTouchTrigger(minorah);
minorah.extra['touchtrigger'].addEventListener('trigger', (THREE.Event event) {
  // 当点击时隐藏模型
  minorah.visible = false;
});

地形与碰撞检测

// 加载地形模型
var manager = THREE.LoadingManager();
var mtlLoader = THREE_JSM.MTLLoader(manager);
mtlLoader.setPath('assets/models/temple/');
var materials = await mtlLoader.loadAsync('temple.mtl');
await materials.preload();
var loader = THREE_JSM.OBJLoader(null);
loader.setMaterials(materials);
Group mesh = await loader.loadAsync('assets/models/temple/temple.obj');
scene.add(mesh);

// 初始化地形数据
OPENWORLD.Space.init(mesh, scene);

热重载功能

hotload() async {
  _hotload.clear();

  // 定义多个草的位置
  const grassposs = [
    [13.61, 1.54, 0.0, 4],
    [14.41, 1.82, 0.0, 4],
    [16.67, 1.33, 0.0, 4],
    [14.60, 5.79, 0.0, 4],
    [59.54, -0.12, 0, 4],
    [58.10, 0.35, 0, 4]
  ];

  // 加载草的纹理
  var grass = await OPENWORLD.Sprite.loadSprite(
      'assets/textures/grass.png', 0.1, 0.1);

  // 克隆草并放置在不同位置
  for (var tree in grassposs) {
    var cyprusii = await OPENWORLD.Sprite.cloneSprite(grass);
    OPENWORLD.Space.worldToLocalSurfaceObj(cyprusii, tree[0].toDouble(),
        tree[1].toDouble(), tree[2].toDouble());
    _hotload.add(cyprusii);
  }
}

更多关于Flutter开放世界探索插件openworld的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter开放世界探索插件openworld的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


openworld 是一个用于 Flutter 的开放世界探索插件,它可以帮助开发者在应用中实现开放世界的探索功能,如地图导航、地点标记、路径规划等。以下是如何使用 openworld 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 openworld 插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  openworld: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入 openworld 插件。

import 'package:openworld/openworld.dart';

3. 初始化插件

在使用 openworld 插件之前,通常需要对其进行初始化。

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await OpenWorld.initialize();
  runApp(MyApp());
}

4. 使用地图组件

openworld 插件通常提供了一个地图组件,你可以将其添加到你的应用中。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Open World Exploration'),
        ),
        body: OpenWorldMap(),  // 使用地图组件
      ),
    );
  }
}

5. 添加标记

你可以在地图上添加标记来表示特定的地点。

OpenWorldMap(
  markers: [
    Marker(
      id: '1',
      position: LatLng(37.7749, -122.4194),  // 经纬度
      infoWindow: InfoWindow(title: 'San Francisco'),
    ),
  ],
);

6. 路径规划

openworld 插件还支持路径规划功能,你可以指定起点和终点来生成路径。

OpenWorldMap(
  onMapCreated: (controller) {
    controller.addPolyline(
      Polyline(
        polylineId: PolylineId('route'),
        points: [
          LatLng(37.7749, -122.4194),  // 起点
          LatLng(34.0522, -118.2437),  // 终点
        ],
        color: Colors.blue,
        width: 5,
      ),
    );
  },
);

7. 处理用户交互

你可以监听用户在地图上的交互事件,如点击、长按等。

OpenWorldMap(
  onTap: (LatLng location) {
    print('Map tapped at $location');
  },
);

8. 自定义样式

openworld 插件通常允许你自定义地图的样式,如颜色、字体等。

OpenWorldMap(
  mapType: MapType.normal,
  style: '''
    [
      {
        "featureType": "water",
        "elementType": "geometry",
        "stylers": [
          { "color": "#0000ff" }
        ]
      }
    ]
  ''',
);

9. 处理权限

在使用地图功能时,通常需要处理位置权限。

import 'package:permission_handler/permission_handler.dart';

void checkLocationPermission() async {
  var status = await Permission.location.status;
  if (!status.isGranted) {
    await Permission.location.request();
  }
}
回到顶部