我正在使用android SDK,Eclipse和AndEngine 我创造了河内塔游戏,与3环完美配合。 当我再添加一个响铃时程序出现故障。 我该如何解决这个问题?这是由我的第四环的尺寸引起的 或者是要设置的代码中的某些内容? 这是我的代码,有4个环,在2,4环或1,3环之间的碰撞时崩溃,依此类推。
@Override
protected void onCreateResources() {
try {
main_font = FontFactory.create(this.getFontManager(), this.getTextureManager(), 256, 256, BitmapTextureFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, Typeface.DEFAULT, 40, true, Color.BLUE);
main_font.load();
// 1 - Set up bitmap textures
backgroundTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/background.png");
}
});
ITexture towerTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/tower.png");
}
});
ITexture ring1 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring1.png");
}
});
ITexture ring2 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring2.png");
}
});
ITexture ring3 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring3.png");
}
});
ITexture ring4 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring4.png");
}
});
mButtonTextureRegion = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/button.png");
}
});
// 2 - Load bitmap textures into VRAM
backgroundTexture.load();
towerTexture.load();
ring1.load();
ring2.load();
ring3.load();
ring4.load();
mButtonTextureRegion.load();
// try {
// this.mBitmapTextureAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(0, 2, 1));
// this.mBitmapTextureAtlas.load();
//} catch (TextureAtlasBuilderException e) {
// Debug.e(e);
//}
this.mBackgroundTextureRegion = TextureRegionFactory.extractFromTexture(backgroundTexture);
this.mTowerTextureRegion = TextureRegionFactory.extractFromTexture(towerTexture);
this.mRing1 = TextureRegionFactory.extractFromTexture(ring1);
this.mRing2 = TextureRegionFactory.extractFromTexture(ring2);
this.mRing3 = TextureRegionFactory.extractFromTexture(ring3);
this.mRing4 = TextureRegionFactory.extractFromTexture(ring4);
this.mbutton = TextureRegionFactory.extractFromTexture(mButtonTextureRegion);
// 4 - Create the stacks
this.mStack1 = new Stack<Ring>();
this.mStack2 = new Stack<Ring>();
this.mStack3 = new Stack<Ring>();
// mButtonTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBitmapTextureAtlas,this,"rectangle_one.png", 2,1);
} catch (IOException e) {
Debug.e(e);
}
}
@Override
protected Scene onCreateScene() {
Sprite backgroundSprite = new Sprite(0, 0, this.mBackgroundTextureRegion, getVertexBufferObjectManager());
scene.attachChild(backgroundSprite);
// 2 - Add the towers
mTower1 = new Sprite(195, 63, this.mTowerTextureRegion, getVertexBufferObjectManager());
mTower2 = new Sprite(450, 63, this.mTowerTextureRegion, getVertexBufferObjectManager());
mTower3 = new Sprite(654, 63, this.mTowerTextureRegion, getVertexBufferObjectManager());
//mbutton = (ITextureRegion) new Sprite(604, 463, (ITextureRegion) this.mButtonTextureRegion, getVertexBufferObjectManager());
scene.attachChild(mTower1);
scene.attachChild(mTower2);
scene.attachChild(mTower3);
// 3 - Create the rings
Ring ring1 = new Ring(1, 155, 122, this.mRing1, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring2 = new Ring(2, 134, 162, this.mRing2, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring3 = new Ring(3, 113, 205, this.mRing3, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring4 = new Ring(4, 90, 250, this.mRing4, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
intent= new Intent(this, MainActivity4.class);
ButtonSprite mButtonSprite = new ButtonSprite(670,0, mbutton,
mEngine.getVertexBufferObjectManager())
{
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY){
scene.detachChild(gameOverText);
moves=0;
//scene.reset();
//scene=onCreateScene();
//mEngine.setScene(scene);
startActivity(intent);
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
scene.attachChild(ring1);
scene.attachChild(ring2);
scene.attachChild(ring3);
scene.attachChild(ring4);
//button.setPosition(0, 200);
scene.attachChild(mButtonSprite);
// 4 - Add all rings to stack one
this.mStack1.add(ring4);
this.mStack1.add(ring3);
this.mStack1.add(ring2);
this.mStack1.add(ring1);
// 5 - Initialize starting position for each ring
ring1.setmStack(mStack1);
ring2.setmStack(mStack1);
ring3.setmStack(mStack1);
ring4.setmStack(mStack1);
ring1.setmTower(mTower1);
ring2.setmTower(mTower1);
ring3.setmTower(mTower1);
ring4.setmTower(mTower1);
// 6 - Add touch handlers
scene.registerTouchArea(ring1);
scene.registerTouchArea(ring2);
scene.registerTouchArea(ring3);
scene.registerTouchArea(ring4);
scene.registerTouchArea(mButtonSprite);
scene.setTouchAreaBindingOnActionDownEnabled(true);
countText = new Text(0, 0, main_font, "Moves:"+moves ,10, this.getVertexBufferObjectManager());
countText.setText("Κινήσεις:"+String.valueOf(moves));
countText.setPosition(0,0);
scene.attachChild(countText);
minMoves = new Text(0, 0, main_font, "Κερδίζεις με 15" ,20, this.getVertexBufferObjectManager());
//start = new Button(0, 0, main_font, "Min moves:"+7 ,10, this.getVertexBufferObjectManager());
minMoves.setPosition(260,0);
scene.attachChild(minMoves);
return scene;
}
private void checkForCollisionsWithTowers(Ring ring) {
Stack<Ring> stack = null;
Sprite tower = null;
if (ring.collidesWith(mTower1) && (mStack1.size() == 0 ||
ring.getmWeight() < ((Ring) mStack1.peek()).getmWeight())) {
stack = mStack1;
tower = mTower1;
moves++;
} else if (ring.collidesWith(mTower2) && (mStack2.size() == 0 ||
ring.getmWeight() < ((Ring) mStack2.peek()).getmWeight())) {
stack = mStack2;
tower = mTower2;
moves++;
} else if (ring.collidesWith(mTower3) && (mStack3.size() == 0 ||
ring.getmWeight() < ((Ring) mStack3.peek()).getmWeight())) {
stack = mStack3;
tower = mTower3;
moves++;
} else {
stack = ring.getmStack();
tower = ring.getmTower();
}
ring.getmStack().remove(ring);
if (stack != null && tower !=null && stack.size() == 0) {
ring.setPosition(tower.getX() + tower.getWidth()/2 -
ring.getWidth()/2, tower.getY() + tower.getHeight() -
ring.getHeight());
} else if (stack != null && tower !=null && stack.size() > 0) {
ring.setPosition(tower.getX() + tower.getWidth()/2 -
ring.getWidth()/2, (stack.peek()).getY() -
ring.getHeight());
}
stack.add(ring);
ring.setmStack(stack);
ring.setmTower(tower);
if(countText != null){
countText.setText("Κινήσεις:"+ moves);
}
scene.detachChild(gameOverText);
//check if game is over
if (isGameOver())
{
moves=0;
}
}
private Boolean isGameOver() {
String gameover;
if(mStack3.size() == 4 ||mStack2.size() == 4 ){
if (moves>15)
{
gameover="Εχασες "+moves+" κινήσεις";
}
else
{
gameover="Κέρδισες!";
}
Font main_font = FontFactory.create(this.getFontManager(), this.getTextureManager(), 256, 256, BitmapTextureFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, Typeface.DEFAULT, 60, true, Color.GREEN);
main_font.load();
gameOverText = new Text(0, 0, main_font, gameover, this.getVertexBufferObjectManager())
{
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY){
//scene.clearTouchAreas();
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
gameOverText.setPosition(CAMERA_WIDTH/2 - gameOverText.getWidth()/2, CAMERA_HEIGHT - 2*gameOverText.getHeight());
scene.attachChild(gameOverText);
//scene.clearTouchAreas();
return true;
}
return false;
}
但是这段代码适用于3环。
@Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
@Override
protected void onCreateResources() {
try {
//this.mBitmapTextureAtlas = new BuildableBitmapTextureAtlas(this.getTextureManager(), 512, 512);
//mButtonTextureRegion = (ITexture) BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "button.png");
//mButtonTextureRegion = (ITexture) BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBitmapTextureAtlas,this,"button.png", 2,1);
main_font = FontFactory.create(this.getFontManager(), this.getTextureManager(), 256, 256, BitmapTextureFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, Typeface.DEFAULT, 40, true, Color.WHITE);
main_font.load();
// 1 - Set up bitmap textures
backgroundTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/background.png");
}
});
ITexture towerTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/tower.png");
}
});
ITexture ring1 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring1.png");
}
});
ITexture ring2 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring2.png");
}
});
ITexture ring3 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring3.png");
}
});
// ITexture ring4 = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
// @Override
// public InputStream open() throws IOException {
// return getAssets().open("gfx/ring4.png");
// }
// });
mButtonTextureRegion = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/button.png");
}
});
mButtonQuitTextureRegion = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/exit_button.png");
}
});
// 2 - Load bitmap textures into VRAM
backgroundTexture.load();
towerTexture.load();
ring1.load();
ring2.load();
ring3.load();
//ring4.load();
mButtonTextureRegion.load();
mButtonQuitTextureRegion.load();
this.mBackgroundTextureRegion = TextureRegionFactory.extractFromTexture(backgroundTexture);
this.mTowerTextureRegion = TextureRegionFactory.extractFromTexture(towerTexture);
this.mRing1 = TextureRegionFactory.extractFromTexture(ring1);
this.mRing2 = TextureRegionFactory.extractFromTexture(ring2);
this.mRing3 = TextureRegionFactory.extractFromTexture(ring3);
//this.mRing4 = TextureRegionFactory.extractFromTexture(ring4);
this.mbutton = TextureRegionFactory.extractFromTexture(mButtonTextureRegion);
this.mbuttonQuit = TextureRegionFactory.extractFromTexture(mButtonQuitTextureRegion);
// 4 - Create the stacks
this.mStack1 = new Stack();
this.mStack2 = new Stack();
this.mStack3 = new Stack();
// mButtonTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBitmapTextureAtlas,this,"rectangle_one.png", 2,1);
} catch (IOException e) {
Debug.e(e);
}
}
@Override
protected Scene onCreateScene() {
Sprite backgroundSprite = new Sprite(0, 0, this.mBackgroundTextureRegion, getVertexBufferObjectManager());
scene.attachChild(backgroundSprite);
// 2 - Add the towers
mTower1 = new Sprite(195, 63, this.mTowerTextureRegion, getVertexBufferObjectManager());
mTower2 = new Sprite(400, 63, this.mTowerTextureRegion, getVertexBufferObjectManager());
mTower3 = new Sprite(604, 63, this.mTowerTextureRegion, getVertexBufferObjectManager());
//mbutton = (ITextureRegion) new Sprite(604, 463, (ITextureRegion) this.mButtonTextureRegion, getVertexBufferObjectManager());
scene.attachChild(mTower1);
scene.attachChild(mTower2);
scene.attachChild(mTower3);
// 3 - Create the rings
Ring ring1 = new Ring(1, 139, 174, this.mRing1, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring2 = new Ring(2, 118, 212, this.mRing2, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring3 = new Ring(3, 97, 255, this.mRing3, getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() != this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
intent= new Intent(this, MainActivity.class);
menu_intent= new Intent(this, MenuActivity.class);
ButtonSprite mButtonSprite = new ButtonSprite(670,0, mbutton,
mEngine.getVertexBufferObjectManager())
{
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY){
scene.detachChild(gameOverText);
moves=0;
//scene.reset();
//scene=onCreateScene();
//mEngine.setScene(scene);
startActivity(intent);
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
ButtonSprite mButtonQuitSprite = new ButtonSprite(670,330, mbuttonQuit,
mEngine.getVertexBufferObjectManager())
{
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY){
//moveTaskToBack(true);
startActivity(menu_intent);
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
scene.attachChild(ring1);
scene.attachChild(ring2);
scene.attachChild(ring3);
//scene.attachChild(ring4);
//button.setPosition(0, 200);
scene.attachChild(mButtonSprite);
scene.attachChild(mButtonQuitSprite);
// 4 - Add all rings to stack one
//this.mStack1.add(ring4);
this.mStack1.add(ring3);
this.mStack1.add(ring2);
this.mStack1.add(ring1);
// 5 - Initialize starting position for each ring
ring1.setmStack(mStack1);
ring2.setmStack(mStack1);
ring3.setmStack(mStack1);
//ring4.setmStack(mStack1);
ring1.setmTower(mTower1);
ring2.setmTower(mTower1);
ring3.setmTower(mTower1);
//ring4.setmTower(mTower1);
// 6 - Add touch handlers
scene.registerTouchArea(ring1);
scene.registerTouchArea(ring2);
scene.registerTouchArea(ring3);
//scene.registerTouchArea(ring4);
scene.registerTouchArea(mButtonSprite);
scene.registerTouchArea(mButtonQuitSprite);
scene.setTouchAreaBindingOnActionDownEnabled(true);
countText = new Text(0, 0, main_font, "Moves:"+moves ,10, this.getVertexBufferObjectManager());
countText.setText("Κινήσεις:"+String.valueOf(moves));
countText.setPosition(0,0);
scene.attachChild(countText);
minMoves = new Text(0, 0, main_font, "Κερδίζεις με 7" ,20, this.getVertexBufferObjectManager());
//start = new Button(0, 0, main_font, "Min moves:"+7 ,10, this.getVertexBufferObjectManager());
minMoves.setPosition(260,0);
scene.attachChild(minMoves);
return scene;
}
private void checkForCollisionsWithTowers(Ring ring) {
Stack stack = null;
Sprite tower = null;
if (ring.collidesWith(mTower1) && (mStack1.size() == 0 ||
ring.getmWeight() < ((Ring) mStack1.peek()).getmWeight())) {
stack = mStack1;
tower = mTower1;
moves++;
} else if (ring.collidesWith(mTower2) && (mStack2.size() == 0 ||
ring.getmWeight() < ((Ring) mStack2.peek()).getmWeight())) {
stack = mStack2;
tower = mTower2;
moves++;
} else if (ring.collidesWith(mTower3) && (mStack3.size() == 0 ||
ring.getmWeight() < ((Ring) mStack3.peek()).getmWeight())) {
stack = mStack3;
tower = mTower3;
moves++;
} else {
stack = ring.getmStack();
tower = ring.getmTower();
}
ring.getmStack().remove(ring);
if (stack != null && tower !=null && stack.size() == 0) {
ring.setPosition(tower.getX() + tower.getWidth()/2 -
ring.getWidth()/2, tower.getY() + tower.getHeight() -
ring.getHeight());
} else if (stack != null && tower !=null && stack.size() > 0) {
ring.setPosition(tower.getX() + tower.getWidth()/2 -
ring.getWidth()/2, ((Ring) stack.peek()).getY() -
ring.getHeight());
}
stack.add(ring);
ring.setmStack(stack);
ring.setmTower(tower);
//gameToast(String.valueOf(moves));
if(countText != null){
countText.setText("Κινήσεις:"+ moves);
}
scene.detachChild(gameOverText);
//check if game is over
if (isGameOver())
{
//toastText("Game over",34, toastLayout,getApplicationContext());
String msg="Game is over with"+String.valueOf(moves)+" moves";
//Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
//gameToast(msg);
moves=0;
}
}
private void resetVars()
{
scene = new Scene();
}
private Boolean isGameOver() {
String gameover;
if(mStack3.size() == 3 ||mStack2.size() == 3 ){
if (moves>7)
{
gameover="Εχασες "+moves+" κινήσεις";
}
else
{
gameover="Κέρδισες!";
}
Font main_font = FontFactory.create(this.getFontManager(), this.getTextureManager(), 256, 256, BitmapTextureFormat.RGBA_8888, TextureOptions.BILINEAR_PREMULTIPLYALPHA, Typeface.DEFAULT, 60, true, Color.RED);
main_font.load();
gameOverText = new Text(0, 0, main_font, gameover, this.getVertexBufferObjectManager())
{
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY){
//scene.clearTouchAreas();
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
gameOverText.setPosition(CAMERA_WIDTH/2 - gameOverText.getWidth()/2, CAMERA_HEIGHT - 2*gameOverText.getHeight());
scene.attachChild(gameOverText);
//scene.clearTouchAreas();
return true;
}
return false;
}
有什么区别?