我在使用机器人的OpenGL-ES做一个游戏,使用多线程:
I'm making a game in android using opengl-es, using multiple threads:
class World{
protected static final AtomicInteger entityLock = new AtomicInteger();
private GameEntity entities[];
public World(){
// populate game world with entities
// executed on main thread
addEntity(new GameEntity("tank"));
addEntity(new GameEntity("rifleman"));
addEntity(new GameEntity("rifleman"));
}
void update(){
synchronized(entityLock){
for(int i = 0;i<entities.length;i++){
// move entity to new position
// executed on PhysThread
entities[i].updatePosition();
}
}
if(entity.isDead(){
// remove entity. Enter sync block inside removeEntity() method
removeEntity(entity);
}
}
void draw(GL10 gl){
synchronized(entityLock){
for(int i = 0;i<entites.length;i++){
// draw models
// executed on GLThread
Vector3 entityPosition = entities[i].getPosition();
gl.glTranslatef(entityPosition.x, entityPosition.y, entityPosition.z);
entities[i].draw();
}
}
}
public void addEntity(GameEntity entity){
synchronized(entityLock){
// arrays stuff
}
}
public void removeEntity(GameEntity entity){
synchronized(entityLock){
// arrays stuff
}
}
}
class MyRenderer implements GLSurfaceView.Renderer{
World world;
public MyRenderer(World world){
this.world = world;
}
public void onDrawFrame(GL10 gl) {
// executed on GLThread
world.draw(gl);
}
}
class PhysThreadRunnable implements Runnable{
private long tickRate = 30;
private World world;
private PhysThreadRunnable(World world){
this.world = world;
}
protected void setTickRate(long tickRate){
this.tickRate = tickRate;
}
public void run() {
while(true){
try {
// executed on PhysThread
world.update();
Thread.sleep(1000/tickRate);
} catch (InterruptedException e) {
return;
}
}
}
}
MyActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
World world = new World();
// sets up the game world, populates it with entities
// set up GLSurfaceView (simplified)
setContentView(R.layout.main);
GLSurfaceView mGLView = findViewById(R.id.myGLSurfaceView);
mGLView.setRenderer(new MyRenderer(world));
// start phys thread
PhysThreadRunnable physThreadRunnable = new PhysThreadRunnable(world);
Thread physThread = new Thread(physThreadRunnable);
physThread.start();
}
}
我有一个有时(但不是每次),当我开始比赛,PhysThread卡住等待被释放锁(即当我去调试和暂停线程,它只是坐在问题同步(entityLock)
在更新()
什么是真正奇怪的是,经过一段时间(2秒和一分钟之间),该PhysThread会畅通,游戏将继续没有任何线程被锁出比线环的几个迭代多。 (即游戏运行罚款)
What's really strange is that after a while (between 2 seconds and a minute), the PhysThread will be unblocked, and the game will continue without either thread getting locked out for more than a few iterations of the thread loops. (i.e. the game runs fine)
编辑:我增加了一些额外的东西的例子,只是这是问题的原因情况。基本上,更新和绘制实体的阵列,而不是一个单一的实体
I added some extra stuff to the example, just in case that is the cause of the problem. Basically, updating and drawing an array of entities rather than a single entity
在最后,我去作弊的解决方案。我把同步块左右进入实体阵列,把一个try / catch语句的ArrayIndexOutOfBounds带内循环:
In the end, I went for the cheat solution. I put the synchronization blocks around access to the entities array and put the for loops inside a try/catch with ArrayIndexOutOfBounds:
void update(){
try{
for(int i = 0;i<entities.length;i++){
GameEntity entity = entities[i];
synchrnonized(entity){
entity.updatePosition();
}
}
}catch(ArrayIndexOutOfBoundsException aioob){
if(tryAgain){
update();
} else {
return;
}
}
}
这个解决方案的问题是,如果 entity.updateposition()
引发 ArrayIndexOutOfBoundsException异常
从完全不相关的东西,然后,我会抓住它,并misinter preT它。再加上整个事情是有点乱,有一次在每一段时间,一帧或更新被跳过
The problem with this solution is that if entity.updateposition()
throws an ArrayIndexOutOfBoundsException
from something completely unrelated, then I'll catch it and misinterpret it. Plus the whole thing is a bit messy, and once in every while, a frame or update gets skipped
由于这似乎解决了这个问题,我怀疑最初的原因很可能在于我的code更深的地方,在进入for循环和实际修改实体之间,我真的不觉得这是公平的在这里倾倒我的整个code。
As this appears to solved the problem, I suspect the original cause probably lies somewhere deeper in my code, between entering the for loops and actually modifying the entities, and I don't really think it'd be fair to dump my entire code here.
我会离开的问题悬而未决的情况下,在任何一两天人有一个更好的解决方案。
I'll leave the question unanswered for a couple days in case anyone else has a better solution
上一篇:获取解析对象ID从onListItemClick对象、ID、onListItemClick
下一篇:在使用Mozilla的Android的WebView显示PDF文件pdf.js低于19的Android API级别级别、文件、oid、WebView