- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在制作一款滑板游戏,您必须使用 box2D 和 AndEngine 跳过障碍。我试图做到这一点,以便当玩家与一个物体碰撞时,该物体被移除并且爆炸被放置在物体的旧位置,但是 Sprite 移除代码中的某些东西正在卡住我的程序导致它结束(甚至不是强制关闭消息它只是自行关闭并转到我的主屏幕)并且 logcat 中没有出现错误/异常信息所以我不知道是什么原因造成的!这是一些代码 fragment -
当我创建 Sprite /边界时,我将一个 JSONObject 附加到包含 Sprite 及其类型的主体,并将一个类似的 JSONOBject 附加到具有主体和类型的 Sprite :
/** method to construct our player (takes an x and y position)*/
private void constructPlayer(final float pX, final float pY) {
final Body body;
/* construct the sprite of our player and set the animation */
this.player = new AnimatedSprite(pX, pY, this.mSkaterTextureRegion);
long[] frameDurations = {100, 100};
player.animate(frameDurations, 4, 5, true);
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, player, BodyType.DynamicBody, PLAYER_FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(player, body, true, false));
body.setUserData(makeUserDataForBody(PLAYER_TYPE,player));
player.setUserData(makeUserDataForSprite(PLAYER_TYPE,body));
this.mScene.registerTouchArea(player);
//attach our player to the scene
this.mScene.attachChild(player);
}
private JSONObject makeUserDataForBody(int type, Object sprite)
{
JSONObject myObject = new JSONObject();
try {
myObject.put("type", type);
myObject.put("sprite", sprite);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myObject;
}
private JSONObject makeUserDataForSprite(int type, Body body)
{
JSONObject myObject = new JSONObject();
try {
myObject.put("body", body);
myObject.put("type", type);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return myObject;
}
我构建障碍 Sprite 的代码与构建播放器几乎相同,但我为它设置了一个移动速度:
private void addObstruction(final float pX, final float pY) {
final Body body;
final Sprite myObstruction;
myObstruction = new Sprite(pX, pY, this.mCrateTextureRegion);
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, myObstruction, BodyType.DynamicBody, OBJECT_FIXTURE_DEF);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(myObstruction, body, true, true));
body.setUserData(makeUserDataForBody(OBSTRUCTION_TYPE,myObstruction));
myObstruction.setUserData(makeUserDataForSprite(OBSTRUCTION_TYPE,body));
body.setLinearVelocity(-150f, 0);
//attach our Obstruction to the scene
this.mScene.attachChild(myObstruction);
}
这是我的物理世界的 contactListener:
this.mPhysicsWorld.setContactListener(new ContactListener() {
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
@Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
Body obj1Data = contact.getFixtureA().getBody();
Body obj2Data = contact.getFixtureB().getBody();
JSONObject obj1UserData;
JSONObject obj2UserData;
int obj1Type = 0;
int obj2Type = 0;
if(obj1Data.getUserData()!=null)
{
obj1UserData =(JSONObject) obj1Data.getUserData();
try {
obj1Type = obj1UserData.getInt("type");
}catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(obj2Data.getUserData()!=null)
{
obj2UserData=(JSONObject) obj2Data.getUserData();
try {
obj2Type = obj2UserData.getInt("type");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
switch (obj1Type)
{
case PLAYER_TYPE:
break;
case GRINDRAIL_TYPE:
if(isGrinding)
{
endGrind();
if(!isJumping)
fall(player);
}
break;
case GROUND_TYPE:
break;
case OBSTRUCTION_TYPE:
break;
case WALL_TYPE:
break;
}
switch (obj2Type)
{
case PLAYER_TYPE:
break;
case GRINDRAIL_TYPE:
if(isGrinding)
{
endGrind();
if(!isJumping)
fall(player);
}
break;
case GROUND_TYPE:
break;
case OBSTRUCTION_TYPE:
break;
case WALL_TYPE:
break;
}
}
@Override
public void beginContact(Contact contact) {
Body obj1Data = contact.getFixtureA().getBody();
Body obj2Data = contact.getFixtureB().getBody();
JSONObject obj1UserData;
JSONObject obj2UserData;
int obj1Type = 0;
int obj2Type = 0;
if(obj1Data.getUserData()!=null)
{
obj1UserData =(JSONObject) obj1Data.getUserData();
try {
obj1Type = obj1UserData.getInt("type");
}catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(obj2Data.getUserData()!=null)
{
obj2UserData=(JSONObject) obj2Data.getUserData();
try {
obj2Type = obj2UserData.getInt("type");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//deal with things colliding with the player
if(obj1Type==PLAYER_TYPE)
{
playerCollisionHandler(obj2Data);
}
else if(obj2Type==PLAYER_TYPE)
{
playerCollisionHandler(obj1Data);
}
}
});
这是我的 playerCollisionHandler 方法:
private void playerCollisionHandler(Body secondBody)
{
JSONObject secondBodyData = null;
if(secondBody.getUserData()!=null)
{
secondBodyData=(JSONObject) secondBody.getUserData();
}
JSONObject userdata = (JSONObject) player.getUserData();
Body playerBody = null;
try {
playerBody = (Body) userdata.get("body");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int objType = 0;
try {
if(secondBodyData!=null)
objType = secondBodyData.getInt("type");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(objType == GROUND_TYPE)
{
if(playerBody.getLinearVelocity().y<0)
{
/* If the sprites y velocity is negative the sprite is jumping,
* don't reset the values!!!*/
}
else
{
if((isJumping)||(isFalling))
{
//play landing sound
AndEngineTestActivity.this.mLandSound.play();
isJumping = false;
isFalling = false;
//player.setPosition(player.getX(), GROUND_LEVEL-player.getHeight());
//animate landing
player.animate(createFrameDurations(LAND_ANIM_FRAMES.length), LAND_ANIM_FRAMES, 0);
}
if(!rollSoundIsPlaying)
{
playRollSound();
}
}
}
else if(objType == GRINDRAIL_TYPE)
{
Sprite grindRail=null;
try {
grindRail = (Sprite) secondBodyData.get("sprite");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*create a rectangle at the upper bound of the grind rail to test collision*/
grindRailUpperBound = new Rectangle(grindRail.getX(), grindRail.getY(), mGrindRailTextureRegion.getWidth(), COLLISION_BOUNDS_PIXEL_ACCURACY);
playerLowerBound = new Rectangle(player.getX(), player.getY()+player.getHeight(), player.getWidth(), COLLISION_BOUNDS_PIXEL_ACCURACY);
grindRailUpperBound.setColor(1.0f, 0f, 0f,1f);
playerLowerBound.setColor(1.0f, 1.0f, 0f,1f);
mScene.attachChild(playerLowerBound);
mScene.attachChild(grindRailUpperBound);
if(grindRailUpperBound.collidesWith(playerLowerBound))
{
if(!isGrinding)
{
mScene.detachChild(grindRailUpperBound);
mScene.detachChild(playerLowerBound);
grindPlayer(player);
}
}
if(!isGrinding)
{
/* if it reaches this point and the custom rectangle bounds did not collide
* it means the player has collided with the grind rail another way, so we hurt the player*/
playerHitByObject();
destroyObstruction(secondBody);
}
}
else if(objType == OBSTRUCTION_TYPE)
{
playerHitByObject();
destroyObstruction(secondBody);
}
}
这里是 destroyObtruction 方法,它似乎是崩溃的罪魁祸首(如果我注释掉我对 destroyObstruction 的调用,我的代码运行正常,但我不确定为什么这个方法会导致崩溃......):
private void destroyObstruction(Body obstructionBody)
{
obstructionBody.setActive(false);
try{
JSONObject secondBodyData = null;
if(obstructionBody.getUserData()!=null)
{
secondBodyData=(JSONObject) obstructionBody.getUserData();
}
explodeObstruction(((IEntity) secondBodyData.get("sprite")).getX(),((IEntity) secondBodyData.get("sprite")).getY());
final PhysicsConnector obstructionPhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape((IShape) secondBodyData.get("sprite"));
this.mPhysicsWorld.unregisterPhysicsConnector(obstructionPhysicsConnector);
this.mPhysicsWorld.destroyBody(obstructionPhysicsConnector.getBody());
//this.mPhysicsWorld.destroyBody(obstructionBody);
this.mScene.detachChild((IEntity) secondBodyData.get("sprite"));
}catch(Exception e)
{
Log.d(TAG, "Exception:"+e);
}
catch(Error e)
{
Log.d(TAG, "Error:"+e);
}
}
private void explodeObstruction(float pX, float pY)
{
PointParticleEmitter obstructionExplosion = new PointParticleEmitter(pX, pY);
ParticleSystem ExplosionParticleSystem = new ParticleSystem(obstructionExplosion, 45, 60, 60, this.mCrateParticleTextureRegion);
ExplosionParticleSystem.addParticleInitializer(new AlphaInitializer(1f));
ExplosionParticleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
ExplosionParticleSystem.addParticleInitializer(new VelocityInitializer(-175, 175, -175, 175));
ExplosionParticleSystem.addParticleInitializer(new RotationInitializer(0.0f, 360.0f));
ExplosionParticleSystem.addParticleInitializer(new RotationInitializer(0f, -20f));
ExplosionParticleSystem.addParticleModifier(new ScaleModifier(1.0f, 0.5f, 0, MAX_PARTICLE_LIFE/2));
ExplosionParticleSystem.addParticleModifier(new AlphaModifier(1, 0.35f, 0, MAX_PARTICLE_LIFE));
ExplosionParticleSystem.addParticleModifier(new ExpireModifier(MAX_PARTICLE_LIFE, MAX_PARTICLE_LIFE));
this.mScene.attachChild(ExplosionParticleSystem);
}
最佳答案
在谷歌搜索 box2D 和 sprite/body 移除后发现你不能从 contactListener 中移除 sprite/body,但是你可以做的是在 body 或 sprite 中设置一个标志来删除它并检查这些在 contactListener 之外的单独更新方法中标记。我通过创建一个“makeUserData”方法来创建一个具有 sprite/body/type 的 JSONObject 以及一个 bool 值“deleteStatus”来确定它是否被标记为删除:
private JSONObject makeUserData(int type, Body body, Object sprite)
{
JSONObject myObject = new JSONObject();
try {
myObject.put("type", type);
myObject.put("sprite", sprite);
myObject.put("body", body);
myObject.put("deleteStatus", false);
} catch (JSONException e) {
// TODO Auto-generated catch block
Log.d(TAG,"Exception creating user data:"+e);
}
return myObject;
}
然后我没有在碰撞后调用 destroyObstruction(),而是调用我创建的这个方法来将主体内的删除标志设置为 true:
private void setForDestruction(Body myBody) throws JSONException
{
if(myBody.getUserData()!=null)
{
((JSONObject)myBody.getUserData()).put("deleteStatus", true);
}
}
然后在一个单独的更新处理程序中(我的 onLoadScene 方法中已经有一个更新分数)我添加了对另一个方法的调用,该方法用于遍历物理世界中的主体以查找此标志:
this.mScene.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() { }
@Override
public void onUpdate(final float pSecondsElapsed) {
//update the players score
updateScore();
//update the text on the screen
playerScoreText.setText( "Score: "+PLAYER_SCORE);
playerLivesText.setText("Lives:"+PLAYER_LIVES);
//remove any sprites flagged for deletion
try{
removeObjectsSetForDestruction();
}catch(Exception e)
{
Log.d(TAG,"Exception removing objects from update:"+e);
}
catch(Error e)
{
Log.d(TAG,"Error removing objects from update:"+e);
}
}
});
这里是 removeObjectsSetForDestruction 方法:
private void removeObjectsSetForDestruction()
{
if(this.mPhysicsWorld!=null)
{
Iterator<Body> allMyBodies = this.mPhysicsWorld.getBodies();//gets all the bodies in my physics world
boolean isDelete = false;
JSONObject currentBodyData;
while(allMyBodies.hasNext())
{
try {
//this code is in a try/catch bracket because some of my bodies don't have the extra data attached
currentBodyData = (JSONObject)allMyBodies.next().getUserData();//gets the next JSONOBject from the body
if(currentBodyData!=null)
{
isDelete = (Boolean) currentBodyData.get("deleteStatus");
if(isDelete)
{
destroyObstruction((Body) currentBodyData.get("body"));
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
Log.d(TAG,"Error getting world bodies data:"+e);
}
}
}
}
编辑:The AndEngine wiki on box2D很好地解释了世界物理计算是如何脆弱的,所以在添加/删除/移动物体时你需要非常小心,因为在某些地方它可能与世界物理计算同时发生,最终导致程序崩溃。它还概述了将代码放入“this.runOnUpdateThread”的解决方案。因此,例如在我的代码中,当我在我的代码中添加一个障碍 Sprite 时(它们是从 CountDownTimer 添加的,因此它们有可能在世界步骤计算的同时添加)我将它包装在一个线程中:
private void addObstruction(final float pX, final float pY) {
runOnUpdateThread(new Runnable() {
@Override
public void run() {
final Body body;
final Sprite myObstruction;
myObstruction = new Sprite(pX, pY-mCrateTextureRegion.getHeight(), mCrateTextureRegion);
body = PhysicsFactory.createBoxBody(mPhysicsWorld, myObstruction, BodyType.DynamicBody, OBJECT_FIXTURE_DEF);
//body.setLinearDamping(10);
//body.setAngularDamping(10);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(myObstruction, body, true, true));
body.setUserData(makeUserData(OBSTRUCTION_TYPE,body,myObstruction));
myObstruction.setUserData(makeUserData(OBSTRUCTION_TYPE,body,myObstruction));
myObstruction.registerUpdateHandler(new IUpdateHandler() {
@Override
public void reset() {
}
@Override
public void onUpdate(float pSecondsElapsed) {
runOnUpdateThread(new Runnable() {
@Override
public void run() {
final Vector2 velocity = Vector2Pool.obtain(-10f, 0f);
body.setLinearVelocity(velocity);
Vector2Pool.recycle(velocity);
}
});
}
});
//attach our Obstruction to the scene
mScene.attachChild(myObstruction);
}
});
}
我在大多数地方使用了这些线程,我用 body 编写代码,我可以确认这停止了我的随机崩溃:)
关于android - AndEngine Sprite/Box2D Body 移除会导致我的程序崩溃且没有错误/异常信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7268778/
我有一段代码看起来像这样: void update_clock(uint8_t *time_array) { time_t time = *((time_t *) &time_array[0]
应用程序崩溃了 :( 请帮助我.. 在这方面失败了。我找不到错误?该应用程序可以连接到 iTunesConnect 但它会出错。 谁能根据下面的崩溃报告判断问题出在哪里? share_with_app
小二是新来的实习生,作为技术 leader,我给他安排了一个非常简单的练手任务,把前端 markdown 编辑器里上传的图片保存到服务器端,结果他真的就把图片直接保存到了服务器上,这下可把我气坏了,就
我正在创建一个函数,它将目录路径作为参数传递,或者如果它留空,则提示用户输入。 我已经设置了我的 PATH_MAX=100 和 if 语句来检查 if ((strlen(folder path) +
我已将“arial.ttf”文件(从我的/Windows/Fonts 文件夹中获取)加载到内存中,但是将其传递到 FT_New_Memory_Face 时会崩溃(在 FT_Open_Face 中的某处
我正在尝试在我的计算机上的两个控制台之间进行 rtsp 流。 在控制台 1 上,我有: ffmpeg -rtbufsize 100M -re -f dshow -s 320x240 -i video=
我正在尝试使用 scio_beast在一个项目中。我知道它还没有完成,但这并不重要。我已经设法让它工作得很好。 我现在正在尝试连接到 CloudFlare 后面的服务器,我知道我需要 SNI 才能工作
我有一个带有关联宏的下拉列表,如下所示: Sub Drop() If Range("Hidden1!A1") = "1" Then Sheets("Sheet1").Se
我对 bash 很陌生。我要做的就是运行这个nvvp -vm /usr/lib64/jvm/jre-1.8.0/bin/java无需记住最后的路径。我认为 instafix 就是这样做...... n
我在 Windows 上使用 XAMPP 已经两年左右了,它运行完美,没有崩溃没有问题。 (直到四个月前。) 大约四个月前,我们将服务器/系统升级到了更快的规范。 这是旧规范的内容 - Windows
我面临着一个非常烦人的 android 崩溃,它发生在大约 1% 的 PRODUCTION session 中,应用程序始终在后台运行。 Fatal Exception: android.app.Re
尝试使用下面的函数: public void createObjectType() { try { mCloudDB.createObjectType(ObjectTypeIn
由于我正在进行的一个项目,我在 CF11 管理员中弄乱了类路径,我设法使服务器崩溃,以至于我唯一得到的是一个漂亮的蓝屏和 500 错误.我已经检查了日志,我会把我能做的贴在帖子的底部,但我希望有人会启
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 10 个月前关闭。 Improve
我最近从 xcode 3.x 更新到 4.2,当我在 4.2 中运行应用程序时,我遇到了核心数据问题。我还更新到了 iOS 5,所以问题可能就在那里,我不太确定。 这些应用程序在 3.x 中运行良好,
我是一个相对较新的 iPhone 应用程序开发人员,所以我的知识有点粗略,所以如果这是一个微不足道的问题,请原谅我。 我有一个导航应用程序,它通过在navigationController对象上调用p
if ([MFMailComposeViewController canSendMail]) { MFMailComposeViewController *mailViewController
你能帮我吗? 我正在设置 UILocalNotification,当我尝试设置其 userInfo 字典时,它崩溃了。 fetchedObjects 包含 88 个对象。 这是代码: NSDi
为什么我的代码中突然出现 NSFastEnumeration Mutation Handler 崩溃。我很茫然为什么会突然出现这个崩溃以及如何解决它。 最佳答案 崩溃错误: **** 由于未捕获的异常
当我从表中删除行时,我的应用程序崩溃了。这是我检测到错误和堆栈跟踪的来源。谢谢! //delete row from database - (void)tableView:(UITableView *
我是一名优秀的程序员,十分优秀!