ok,start!
绘制一个球
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Override
public void create() { ball = new TextureRegion(new Texture(Gdx.files.internal("data/images/ball.png"))); batch = new SpriteBatch(); } @Override public void render() { Gdx.gl.glClearColor(.4f, .4f, .4f, .4f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batch.begin(); batch.draw(ball, 300, 400, ball.getRegionWidth(), ball.getRegionHeight()); batch.end(); } |
接着就来到box2D环节
创建一个世界
* -9.81f是标准重力(怎么算的不知道,这么写就对了)
world = new World(new Vector2(0, -9.81f), true);
|
* -9.81f是标准重力(怎么算的不知道,这么写就对了)
* boolean值是doSleep,大概是没有事情发生的时候会休眠,节省资源吧
创建相机
2 |
camera = new OrthographicCamera();
camera.setToOrtho(false, 1280 / PPM, 720 / PPM); |
* false:是否把相机倒过来
* box2D世界的单位是米,因为box2D不能模拟太巨大的世界,(比如重力加速会无效)
我们又需要保持像素不变,所以这里进行一下换算,1280 / PPM, PPM=100;
结果是 1280像素 = 12.8米,后面box2D相关的数字都要除以PPM
为了能看到线框,创建Debug渲染
debugRenderer = new Box2DDebugRenderer();
|
创建2个刚体,一个地面,一个球
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//Static Body 地面
BodyDef groundBodyDef = new BodyDef(); groundBodyDef.type = BodyDef.BodyType.StaticBody; groundBodyDef.position.set(640 / PPM, 300 / PPM); //形状 PolygonShape staticBox = new PolygonShape(); staticBox.setAsBox(300 / PPM, 20 / PPM); //生成 Body bodyG = world.createBody(groundBodyDef); bodyG.createFixture(staticBox, 0); //Dynamic Body 球 BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyDef.BodyType.DynamicBody; bodyDef.position.set(500 / PPM, 600 / PPM); CircleShape dynamicCircle = new CircleShape(); dynamicCircle.setRadius( 50 / PPM); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = dynamicCircle; fixtureDef.density = 0.7f; // 密度 fixtureDef.friction = 0.4f; // 摩擦 fixtureDef.restitution = 0.8f; // 弹性 body = world.createBody(bodyDef); body.createFixture(fixtureDef); |
* StaticBody可以省略type和FixtureDef,在createFixture的时候是写shape和密度
* BodyDef.position.set 是坐标从起点到圆心的距离
* libgdx的物体x,y值是左下角,box2D是圆心
* libgdx的物体x,y值是左下角,box2D是圆心
* setAsBox & settRadius 设置的都是半径
修改 render()
2 3 4 5 6 7 8 9 10 11 12 13 |
@Override
public void render() { Gdx.gl.glClearColor(.4f, .4f, .4f, .4f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); world.step(1 / 60f, 6, 2); camera.update(); debugRenderer.render(world, camera.combined); batch.begin(); batch.draw(ball, 150, 400, ball.getRegionWidth(), ball.getRegionHeight()); batch.end(); } |
* world.step 时步,60帧每秒就设置为 1/60f,后面2个参数是速率迭代 & 位置迭代,效果不明...
* 更新相机,debug绑定世界和相机
这时候ball和刚体球还没有任何联系,下面就是重点
ball只要绑定刚体的坐标和旋转值,它们就能合体了!
修改 batch.draw
2 3 4 5 |
batch.draw(ball, body.getPosition().x * PPM - ball.getRegionWidth() / 2,
body.getPosition().y * PPM - ball.getRegionWidth() / 2, ball.getRegionWidth() / 2, ball.getRegionHeight() / 2, ball.getRegionWidth(), ball.getRegionHeight(), 1, 1, body.getAngle() * MathUtils.radiansToDegrees); |
* ball,X坐标,Y坐标,X旋转中心,Y旋转中心,宽,高,X缩放,Y缩放,旋转值
* - ball.getRegionWidth() / 2 意思是让坐标回到左下角
在create方法给ball一个加速力, 然后运行
body.setLinearVelocity(2, -2);
|

接下来是地图工具 Tiled map 时间
创建地图用的相机,相当于主角的视角,并载入地图
2 3 4 5 |
mapCam = new OrthographicCamera();
mapCam.setToOrtho(false, 1280, 720); map = new TmxMapLoader().load("data/maps/map1.tmx"); renderer = new OrthogonalTiledMapRenderer(map); |
在render()添加
2 3 |
mapCam.update();
renderer.setView(mapCam); renderer.render(); |
* 此时地图只是个背景,毫无用处
* 为了让ball对地图的墙面有碰撞效果,我们需要绘制2个刚体并定位到墙面上,难点就是如何获取对象层的2个矩形的坐标和宽高
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
MapLayer mapLayer = map.getLayers().get("land");
MapObjects objects = map.getLayers().get("land").getObjects(); ArrayList<Float> listW = new ArrayList<Float>(); ArrayList<Float> listH = new ArrayList<Float>(); BodyDef bdef = new BodyDef(); PolygonShape shape = new PolygonShape(); int i = 0; for(MapObject object : objects) { if (object instanceof RectangleMapObject) { Rectangle rect = ((RectangleMapObject) object).getRectangle(); // do something with rect... listW.add(rect.getWidth()); listH.add(rect.getHeight()); i++; } } Iterator itW = listW.iterator(); Iterator itH = listH.iterator(); for(MapObject mo : mapLayer.getObjects()) { float x = mo.getProperties().get("x", Integer.class) / PPM; float y = mo.getProperties().get("y", Integer.class) / PPM; if(i - 1 > 0) { float w = (Float)itW.next() / 2 / PPM; float h = (Float)itH.next() / 2 / PPM; shape.setAsBox(w, h); bdef.position.set(x + w, y + h); } world.createBody(bdef).createFixture(shape, 0); } |
* 大意是:获取名为"land"的图层,遍历获取每个形状的宽高,坐标,并生成刚体
* 真实的地图一定不止2块墙面,所以需要用遍历,迭代
不要问我为什么这一大段解释那么少,因为是copy来的
地图只负责静态,能动的东西必须要draw和贴图
没有评论:
发表评论