Bullet(cocos2dx)学习制作桌球游戏之前期准备

使用cocos2dx结合bullet设计一款简陋的桌球游戏,就是为了回顾前期学过的bullet。

首先要把桌球游戏需要的基本资源准备好,15个球,1个白球,1张台球桌,球杆可有可无。

先看看目前实现的效果

至于这张台球桌的模型,我是随便设计一下

当然这个模型只是为了加载raw文件(静态网格数据),为了使模型的贴图显示出来,

我使用Blender直接创建了一个Plane,然后将台球桌的贴图贴在Plane上,于是就能以假乱真的

实现一个台球桌

在游戏开始前,初始化物理环境,加载一张台球桌,设置相应的物理属性,按规则摆放好台球。

1.设置重力为(0.f, -9.8f, 0.f),以模拟真实的物理环境。

_world = PhysicsWorld3D::createWithDebug(this, btVector3(0.f, -9.8f, 0.f));

2.加载台球桌

首先将台球桌的贴图模型加载进游戏,设置相应的位置,

然后加载台球桌的物理网格,还记得PhysicisMesh3D吗,并调整好位置,

当然比较不好设置的就是台球桌的物理属性,什么摩擦系数啊,弹性系数啊,滚动摩擦系数啊

void HelloWorld::initTable()
{
	auto tableSprite = Sprite3D::create("ball/table.c3b");
	this->addChild(tableSprite);
	tableSprite->setPosition3D(Vec3(0.f, -0.57f, 0.f));
	tableSprite->setCameraMask(2);

	_tableMesh = PhysicsMesh3D::constuct("table.raw");
	_world->addTriangleMesh(_tableMesh, btVector3(0, -0.57f, 0), PhysicsMaterial3D(0.f, 0.5f, 0.2f, 0.2f));
}

3.摆放台球

对于15球来说摆放的顺序是这样的,在网上找的规则

黑8放在第三行的中间位置,白色的为全色球,黑色的为花色球。

可以这样设想,只要定义一个数组存放每个位置的球号就行了,

BALLS_NUMBER[0] = 1;

BALLS_NUMBER[1] = 2;

BALLS_NUMBER[2] = 9;

BALLS_NUMBER[3] = 10;

BALLS_NUMBER[4] = 8;

BALLS_NUMBER[5] = 3;

BALLS_NUMBER[6] = 4;

BALLS_NUMBER[7] = 11;

BALLS_NUMBER[8] = 5;

BALLS_NUMBER[9] = 12;

BALLS_NUMBER[10] = 13;

BALLS_NUMBER[11] = 6;

BALLS_NUMBER[12] = 14;

BALLS_NUMBER[13] = 15;

BALLS_NUMBER[14] = 7;

球号是我自己按照规则随便放的。

下面就是如果将这些球放好,

假设每个球半径为0.57f,球都在Y坐标为0的位置,那么关键就是如何确定每个球的

X,Z.台球摆放好无论多少行都是个等边三角形,以3行为例

先放置第一个球,以后每一行的第一个球都是按照蓝色箭头的方向放置,假设上为Z,右为X

那么第二行第一个球就是(ball[1].posX + ball.radius, ball[1].posZ + √3*ball.radius)

设方向向量为dir(ball.radius, 0, √3*ball.radius);

即ball[2].pos = ball[1].pos + dir

第三行就是ball[3].pos = ball[1].pos + dir * 2;

一次类推ball[n].pos = ball[1].pos + dir * (n-1);

对于同一行的第k个球就是同一行的第一个球.pos.x - 2 * radius;

Sprite3D* ballSprite;
	btRigidBody* ballBody;

	int curNumber = -1;
	float offsetZ = -7.f;
	Vec3 ballPos;
	const Vec3 dir = Vec3(-0.57f, 0.f, -0.987269f);

	for (int i=0; i<5; ++i)
	{
		ballPos = dir * i;
		ballPos.x += -1.14f;
		ballPos.z += offsetZ;
		for (int j=0; j<=i; ++j)
		{
			curNumber++;		// 第几个球
			ballPos.x += 1.14f;  // 每行第k个都是上一个球的X+ 2 * radius

			ballSprite = Sprite3D::create("ball/ball.c3b", StringUtils::format("ball/ball_%d.png", BALLS_NUMBER[curNumber]));
			this->addChild(ballSprite);
			ballSprite->setPosition3D(ballPos);
			ballSprite->setCameraMask(2);

			ballBody = _world->addSphere(0.57f, btVector3(ballPos.x, ballPos.y, ballPos.z), PhysicsMaterial3D(4.2f, 0.2f, 0.9f, 0.15f));
			ballBody->setUserPointer(ballSprite);

			_balls.push_back(ballBody);
		}
	}

看上面代码

Sprite3D::create("ball/ball.c3b",
StringUtils::format("ball/ball_%d.png", BALLS_NUMBER[curNumber]));

根据提前的设计加载相应的球号。

ballPos = dir * i;

ballPos.x += -1.14f;

ballPos.z += offsetZ;

设置每行第一个球的位置

最后就是加载白球,白球要特别独立出来

// white ball
	ballSprite = Sprite3D::create("ball/ball.c3b", "ball/ball_white.png");
	this->addChild(ballSprite);
	ballSprite->setPosition3D(Vec3(0.f, 0.f, 5.f));
	ballSprite->setCameraMask(2);
	_whiteBallBody = _world->addSphere(0.57f, btVector3(0.f, 0.f, 5.f), PhysicsMaterial3D(4.2f, 0.2f, 0.9f, 0.15f));
	_whiteBallBody->setUserPointer(ballSprite);

4.更新物理世界

_world->update(delta);

	float m[16];
	for (auto ballBody : _balls)
	{
		ballBody->getWorldTransform().getOpenGLMatrix(m);
		static_cast<Sprite3D*>(ballBody->getUserPointer())->setNodeToParentTransform(Mat4(m));
	}

	_whiteBallBody->getWorldTransform().getOpenGLMatrix(m);
	static_cast<Sprite3D*>(_whiteBallBody->getUserPointer())->setNodeToParentTransform(Mat4(m));

每一帧都去更新实际上是很浪费资源的,当所有的球都不动时,其实没必要更新,但是只有不到20个球,

性能不会影响,当游戏中出现大量的物体时,就要重载btMotionState,这个以后讨论。

5.测试一下

当点击屏幕是给白球施加一个冲量,记住一定要先唤醒物体,不然不会有效果的

_whiteBallBody->setActivationState(ACTIVE_TAG);

_whiteBallBody->applyCentralImpulse(btVector3(0.f, 0.f, -60.5f));

总结:

不是美工,模型什么的设计很费劲,贴图都是网上找的。

台球桌,台球的物理属性,调整麻烦,目前调整的还不好

对于添加的Sprite3D一定要设置CameraMask不然是不会被看到的。

添加光照,使物体具有立体感

// light
	auto light = SpotLight::create(Vec3(0, -1.f, 0.f), Vec3(0.f, 0.f, 0.f), Color3B::WHITE, 0.f, 0.5f, 1000.f);
	light->setPosition3D(Vec3(0.f, 100.f, 0.f));
	this->addChild(light);
	light->setCameraMask(2);

源码下载

Bullet库的设置方法请参考http://blog.csdn.net/ctxdecs/article/details/42045099

时间: 2024-12-15 15:37:12

Bullet(cocos2dx)学习制作桌球游戏之前期准备的相关文章

cocos2d-x学习笔记(18)--游戏打包(windows平台)

cocos2d-x学习笔记(18)--游戏打包(windows平台) 之前做好的游戏,都是在vs2008下编译执行的.假设说想把游戏公布到网上或者和其它人一起分享游戏,那就得对游戏进行打包.以下我就向大家介绍一款程序打包工具 ----Enigma Virtual Box,这个软件的下载链接我就不提供了,大家在网上输入这个keyword,就有非常多下载链接了. 既然要执行游戏,就得找到.exe文件.有些人可能打开project文件夹下(我的是myGame01)的Debug.win32文件夹找.但没

学习制作SLG游戏(一)

    好吧,最近迷上了海岛奇兵,打算学习学习SLG的游戏开发,教程参考: [系列原创教程]制作基于Cocos2d-x的SLG游戏.貌似原教程没有素材,我就只在第四章找到了一个类似素材...但是后来发现貌似图片大小不对,然后自己用PS放大拉一下...好吧,说我照本宣科也好,反正第一次学习,还是跟着教材来比较好. 自己放大的素材:ios-test-128.png,大概样子如下 自己画了背景的一堆树的背景图:1.png, 大概样子如下

Cocos2d-x中由sprite来驱动Box2D的body运动(用来制作平台游戏中多变的机关)

好久都没写文章了,就来一篇吧.这种方法是在制作<胖鸟大冒险>时用到的.<胖鸟大冒险>中使用Box2D来进行物理模拟和碰撞检測,因此对每一个机关须要创建一个b2body.然后<胖鸟>是依据<超级马里奥兄弟>设计的,所以机关能够是各种运动轨迹的平台,绕圈转的乌龟,蹦蹦跳的乌龟等.假设用box2d来做这些运动的话要自己写这些轨迹.可是Cocos2d-x已经提供了非常多的action,自己添加action也非常方便.反过来用sprite去设置box2d的b2body

Cocos2d-x学习资源集锦+有奖抽楼活动

大家好,事实上我是这个游戏开发版块的新任版主之中的一个,可能大家的焦点都在candycat1992女版主身上,所以我认为我应该冒个泡. 俗话说,新版主上任,三把"水"(是你自己说的吧,喂.).今天第一天上任,怎么都得贡献一下,做个样子什么的还是非常必要的(喂,太诚实了吧.) 本人主要研究的是Cocos2d-x,所以今天就来给各位提供一些关于Cocos2d-x学习的好去处吧.可能有经验的朋友都知道这些地方.这里就献给刚開始学习的人吧. PS:抽奖活动在以下一点.别急~ Cocos2d-x

【Cocos2D-X 学习笔记】为精灵添加单点触控

由于Cocos2d-x处于新学的阶段,因此最近也无法进行系统地更新,只会选择一些典型的Demo贴上来,一来是与大家分享,而来也可以作为以后回顾时的参考. 今天介绍一下Cocos2d-x的触摸事件处理,了解Android开发的朋友们知道,Android里会用一个OnClickListener()进行事件监听,而在J2SE中也会有Event类实现专门的监听处理.在Cocos2d-x中,因为是游戏引擎,用户在玩游戏时总是要通过屏幕与游戏进行交互,可想而知触摸事件是主要处理的事件.这里主要讲一下如何为精

cocos2dx学习笔记(2)

昨天尝试了cocos2dx在win下的开发环境配置,并且运行了cocos的helloword程序,晚上想要尝试一下android开发环境配置,顺便学习cocos在eclipse下的JNI机制,按照cocoa中文论坛的android环境配置弄了NDK,并配置了环境变量,由于想要学习cocos的luabind机制(这个我们公司游戏的引擎用的很多,确实比较有兴趣),一切搞定不明就里的用eclipse导入了cocos3.0rc中的tests目录下的cpp-tests工程(这算android开发久了的毛病

cocos2d-x 学习资源整理(持续更新...)

生活像一把无情刻刀,改变了我们模样,曾经我以为会亘古不变的东西,突然在一瞬间失去了信念... 如果你改变不了生活中患得患失的心情,那就试着让自己变得强大一点,因为能做到不以物喜不以己悲都是建立在强大的基础上面的. so,加油吧,少年. ================================================================ 一不小心又废话了. 学习cocos2d-x也有一段时间了,直到现在仍然认为自己是个新手(呵呵,说的好像我不是新手一样.) 现在把自己这

COCOS2DX学习之Box2d物理引擎使用之------动态物体的创建

1.创建一个物理世界 首先要引入一个头文件#include "Box2D\Box2D.h" 之后利用b2word创建一个对象,并且指定这个物理世界中的加速度方向. word = new b2World(b2Vec2(0,-10));                        //指定物理世界的加速度 最后还要重写一下update函数,这个函数在之前的计时器学习的时候已经说过,每一帧的变动都将自动执行这个函数.所以我们要通过这个函数来进行创建的物理世界的刷新. 2.创建一个运动的物体

cocos2d-x学习日志(18) --程序是如何开始运行与结束?

问题的由来 怎么样使用 Cocos2d-x 快速开发游戏,方法很简单,你可以看看其自带的例程,或者从网上搜索教程,运行起第一个HelloWorld,然后在 HelloWorld 里面写相关逻辑代码,添加我们的层.精灵等 ~ 我们并不一定需要知道 Cocos2d-x 是如何运行或者在各种平台之上运行,也不用知道 Cocos2d-x 的游戏是如何运行起来的,它又是如何渲染界面的 ~~~ 两个入口 程序入口的概念是相对的,AppDelegate 作为跨平台程序入口,在这之上做了另一层的封装,封装了不同