#Andengine##Box2D#-----前轮驱动赛车

2023-11-11 01:31

本文主要是介绍#Andengine##Box2D#-----前轮驱动赛车,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


一. 实现功能:

应用Andengine引擎+Box2D物理引擎,实现“前轮驱动”赛车.

二. 相关代码:

1. 在游戏场景中创建物理世界:

FixedStepPhysicsWorld mPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0f, 0f), false, 8, 3);  //创建物理世界,将重力设置为0
registerUpdateHandler(mPhysicsWorld); //在当前场景中注册该物理世界

2. 创建汽车主体部分:

public static final FixtureDef CAR_DEF = PhysicsFactory.createFixtureDef(1f, 1f, 1f, false);Sprite CarShape=new Sprite(); //创建汽车主体精灵
GameScene.attach(CarShape);	//将精灵附加到场景中Body carBody = PhysicsFactory.createBoxBody(Registry.sGameScene.mPhysicsWorld,CarShape,BodyDef.BodyType.DynamicBody,Registry.sGameScene.CAR_DEF);  //根据汽车主体精灵创建Body
carBody.setLinearDamping(1);   //设置线性方向上的阻尼
carBody.setAngularDamping(1);	//设置转动阻尼
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(CarShape, carBody, true, true)); //将Sprite和Body进行连接

3. 创建四个轮胎:

public static final FixtureDef WHEEL_DEF = PhysicsFactory.createFixtureDef(1f, 1f, 1f, false);//右前轮(Sprite+Body):
rightTopWheel=new Sprite(CarShape.getX()+CarShape.getWidth()*0.5f,CarShape.getY()+18,ResourceManager.getInstance().WheelRegion,ResourceManager.getInstance().vbom);
Registry.sGameScene.attachChild(rightTopWheel);  rightTopBody = PhysicsFactory.createBoxBody(Registry.sGameScene.mPhysicsWorld,rightTopWheel,BodyDef.BodyType.DynamicBody, Registry.sGameScene.WHEEL_DEF);
Registry.sGameScene.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(rightTopWheel, rightTopBody, true, true));//左前轮(Sprite+Body):
leftTopWheel=new Sprite(CarShape.getX()-CarShape.getWidth()*0.5f,CarShape.getY()+18,ResourceManager.getInstance().WheelRegion,ResourceManager.getInstance().vbom);
Registry.sGameScene.attachChild(leftTopWheel);leftTopBody = PhysicsFactory.createBoxBody(Registry.sGameScene.mPhysicsWorld,leftTopWheel,BodyDef.BodyType.DynamicBody, Registry.sGameScene.WHEEL_DEF);Registry.sGameScene.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(leftTopWheel, leftTopBody, true, true));//右后轮(Sprite+Body):
rightDownWheel=new Sprite(CarShape.getX()+CarShape.getWidth()*0.5f,CarShape.getY()-18,ResourceManager.getInstance().WheelRegion,ResourceManager.getInstance().vbom);
Registry.sGameScene.attachChild(rightDownWheel);rightDownBody = PhysicsFactory.createBoxBody(Registry.sGameScene.mPhysicsWorld,rightDownWheel,BodyDef.BodyType.DynamicBody, Registry.sGameScene.WHEEL_DEF);
Registry.sGameScene.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(rightDownWheel, rightDownBody, true, true));//左后轮(Sprite+Body)
leftDownWheel=new Sprite(CarShape.getX()-CarShape.getWidth()*0.5f,CarShape.getY()-18,ResourceManager.getInstance().WheelRegion,ResourceManager.getInstance().vbom);
Registry.sGameScene.attachChild(leftDownWheel);leftDownBody = PhysicsFactory.createBoxBody(Registry.sGameScene.mPhysicsWorld,leftDownWheel,BodyDef.BodyType.DynamicBody, Registry.sGameScene.WHEEL_DEF);
Registry.sGameScene.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(leftDownWheel, leftDownBody, true, true));

4.将轮胎与汽车主体进行关联:

(1). RevoluteJoint (旋转关节) ----前轮
因为前轮负责方向的引导(即转向,方向盘控制前轮),所以需要使用旋转关节

private RevoluteJoint mJointRightTop;  
private RevoluteJointDef rtjd; rtjd.initialize(carBody, rightTopBody, rightTopBody.getWorldCenter()); //将车体Body与右前轮Body进行连接,连接中心设为车胎中心
rtjd.enableMotor=true;   //旋转关节开启扭矩
rtjd.maxMotorTorque=100;  //最大扭矩设置为100
mJointRightTop= (RevoluteJoint)Registry.sGameScene.mPhysicsWorld.createJoint(rtjd);  //在物理世界中注册该关节

(2). PrismaticJoint(平行关节)----后轮
后轮只需要跟随车辆主体进行运动

PrismaticJointDef jd=new PrismaticJointDef();
Joint mJointRightDown=null;jd.initialize(carBody, rightDownBody, rightDownBody.getWorldCenter(),new Vector2(1,0)); //将右后轮Body与车主体Body进行平行关节连接
jd.enableLimit=true; //设置为跟随车动
jd.lowerTranslation=0;
jd.upperTranslation=0;
mJointRightDown=Registry.sGameScene.mPhysicsWorld.createJoint(jd);  //注册关节


5. 场景Update循环中控制车辆移动与转向:

*Box2D知识点: Body.getTransform() ---->获得Body的位置及速度,通过位置和速度能得到向量。也可以通过vals来简便获得
Body X轴的方向向量:
Vector2 d=new Vector2(Body.getTransform().vals[2],Body.getTransform().vals[3]);


Body Y轴的方向向量:
Vector2 d=new Vector2(Body.getTransform().vals[4],Body.getTransform().vals[5]);

public static double MAX_STEER_ANGLE = Math.PI/3;  //最大扭矩
public static float STEER_SPEED = 1.5f;    //转向速度
public static float HORSEPOWERS = 20f;     //马力public float engineSpeed;
public double steeringAngle;场景循环:(Update)
//前进
sideXR = (float)myCar.getRightTopBody().getTransform().vals[4];
sideYR = (float)myCar.getRightTopBody().getTransform().vals[5];
Vector2 rdirection=new Vector2(sideXR,sideYR);  //获得右前胎Y轴的方向向量
rdirection.mul(engineSpeed);         //方向向量*动力=作用力sideXL = (float)myCar.getLeftTopBody().getTransform().vals[4];
sideYL = (float)myCar.getLeftTopBody().getTransform().vals[5];
Vector2 ldirection=new Vector2(sideXL,sideYL);  //获得左前胎Y轴的方向向量
ldirection.mul(engineSpeed);		//方向向量*动力=作用力myCar.getRightTopBody().applyForce(ldirection, myCar.getRightTopBody().getPosition());  //施加右前胎作用力
myCar.getLeftTopBody().applyForce(rdirection, myCar.getLeftTopBody().getPosition());	//施加左前胎作用力//转向
float mspeed;
mspeed=(float)(steeringAngle-myCar.getmJointRightTop().getJointAngle());    //获得转向扭矩力
myCar.getmJointRightTop().setMotorSpeed(mspeed * STEER_SPEED);			//施加转向扭矩力mspeed=(float)(steeringAngle-myCar.getmJointLeftTop().getJointAngle());
myCar.getmJointLeftTop().setMotorSpeed(mspeed * STEER_SPEED);

6. 创建前进与转向按钮:

前进:
                engineSpeed=-CarManager.getInstance().HORSEPOWERS;

转向:(右转)
    steeringAngle=-CarManager.getInstance().MAX_STEER_ANGLE;

释放以后:
    engineSpeed=0;
    steeringAngle=0;


最后附上项目的demo供参考:

下载地址:http://pan.baidu.com/s/1jGkJbdc 


这篇关于#Andengine##Box2D#-----前轮驱动赛车的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/386654

相关文章

【#第三期实战营闯关作业 ## 茴香豆:企业级知识库问答工具】

今天学习了《 茴香豆:企业级知识库问答工具》这一课,对大模型的应用有了更深得认识。以下是记录本课实操过程及截图: 搭建茴香豆虚拟环境: 输入以下命令 ``studio-conda -o internlm-base -t huixiangdou 成功安装虚拟环境截图 安装茴香豆 cd /root 克隆代码仓库 git clone https://github.com/internlm/h

C语言宏定义中#和##的作用

在宏定义中#和##的作用是:前者将宏定义的变量转化为字符串;后者将其前后的两个宏定义中的两个变量无缝拼接在一起转化为字符串。 1.   #: 在宏定义中,将其后的变量,转化为字符串。     eg:  #define  str(s)      #s   输出: helloworld , 就可以通过这样的的调用, printf( str(helloworld) ); 2. ## :

【C++】define宏定义中的#,##,@#及\符号

一、# 名称:字符串化操作符 其作:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。 使用条件:只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前 举例: #define example1(instr) #instr string str=example1(abc); 将会展成:string str="abc"; 注意:对空格的处理 a、忽略传入参数名前面和后

【#第三期实战营闯关作业 ## MindSearch CPU-only 版部署】

这是进阶闯关的最后一课,把MindSearch 部署到Github Codespace 和 Hugging Face Space,这是一种新的痛并快乐的体验,亦因i踩了不少坑。以下是记录的复现过程及截图; 登录github网站,打开codespace主页,选择blank template,浏览器自动在新的页面打开一个web版的vscode。然后就可以新建一个目录用于存放 MindSearch 的相

【#第三期实战营闯关作业##LMDeploy 量化部署进阶实践 】

今天学习了《LMDeploy 量化部署进阶实践》一课,,收获很大。以下是记录复现过程及截图: 创建一个名为lmdeploy的conda环境 创建成功后激活环境并安装0.5.3版本的lmdeploy及相关包。 相关包install成功 创建好的conda环境并启动InternLM2_5-7b-chat。这是对话截图 运行InternLM2.5 -20B模型,会发现此时显存占用大约71G:单卡80

微博话题正则表达式匹配 ##

import java.util.LinkedHashSet;import java.util.Set;import java.util.regex.Matcher;import java.util.regex.Pattern;/*** @author XXX* Date: 2019/3/20* Description:*/public class RegexpUtil {/***

C语言宏定义中#和##运算符

宏定义可以包含两个专用的运算符:#和## 1, #运算符 #运算符将宏的一个参数转换为字符串字面量,所执行的操作可以理解为“字符串化”。它仅允许出现在带参数的宏的替换列表中。举个例子 #define PRINT_INT(n) printf(#n " = %d\n", n) n之前的#运算符通知预处理器根据PRINT_INT的参数创建一个字符串字面量,因此 PRINT_IN

【FreeRTOS】队列实验-分发数据给多个任务(赛车游戏)

目录 0 前言1 队列实验_分发数据给多个任务(赛车游戏)2 赛车游戏2.1 game.c2.2 注册队列2.3显示汽车2.4隐藏汽车2.5 CarTask2.6 car_game2.7 MX_FREERTOS_Init 3 总结 0 前言 学习视频: 【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为

[ARM-2D 专题]3. ##运算符

C语言的宏系统相当强大,它允许使用##符号来处理预处理期的文本替换。这种用法被称为标记连接(token pasting)操作,其结果是将两个标记紧紧地连接在一起,而省略掉它们之间的所有空格。在复杂的宏定义中,运用##可以有效地生成新的标识符或调整代码的结构。对##符号的深入理解可以帮助编写出更高效、更灵活的代码,但同时也需要注意其可能带来的复杂性和可读性问题。 ##运算符,也叫连接运算符(也

在shell里面,“%”、“#”、“*” 是什么意思,如${a%%.*}、${a##*.}

在shell里面,“%”、“#”、“*” 是什么意思,如${a%%.*}、${a##*.} 在shell里面,“%”、“#”、“*” 是什么意思,如${a%%.*}、${a##*.} ${varible##*string}  从左向右截取最后一个string后的字符串 ${varible#*string}   从左向右截取第一个string后的字符串 ${varible%%string*}