1. 程式人生 > >android遊戲引擎andengine學習系列三:繪製遊戲虛擬搖桿

android遊戲引擎andengine學習系列三:繪製遊戲虛擬搖桿

 如何高效的學習,這才是我們最值得去學習的。

andengine中繪製虛擬遊戲搖桿非常簡單,只需要實現AnalogOnScreenControl模擬搖桿類,在設定一些屬性即可。先看效果圖:

左邊的搖桿是控制精靈上下左右移動,右邊的搖桿空值精靈的旋轉。程式碼結構跟andengine學習系列二一樣,其中很多註釋在系列二中有說明,在該章內便不多複述。

onLoadEngine()方法:

@Override
	public Engine onLoadEngine() {
		this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		final Engine engine = new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera));

		try {		//因為有兩個搖桿,需要兩個手指同時進行,所以這裡要註冊多點觸控
			if(MultiTouch.isSupported(this)) {
				engine.setTouchController(new MultiTouchController());
				if(MultiTouch.isSupportedDistinct(this)) {
					Toast.makeText(this, "MultiTouch detected --> Both controls will work properly!", Toast.LENGTH_LONG).show();
				} else {
					this.mPlaceOnScreenControlsAtDifferentVerticalLocations = true;
					Toast.makeText(this, "MultiTouch detected, but your device has problems distinguishing between fingers.\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
				}
			} else {
				Toast.makeText(this, "Sorry your device does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
			}
		} catch (final MultiTouchException e) {
			Toast.makeText(this, "Sorry your Android Version does NOT support MultiTouch!\n\n(Falling back to SingleTouch.)\n\nControls are placed at different vertical locations.", Toast.LENGTH_LONG).show();
		}

		return engine;
	}

onLoadResources()方法:

public void onLoadResources() {

		this.mTexture = new Texture(32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mFaceTextureRegion = TextureRegionFactory.createFromAsset(this.mTexture, this, "face_box.png", 0, 0);

		this.mOnScreenControlTexture = new Texture(256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mOnScreenControlBaseTextureRegion = TextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_base.png", 0, 0);	//這裡是載入搖桿的地盤的紋理圖片 
		this.mOnScreenControlKnobTextureRegion = TextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_knob.png", 128, 0);	//這裡是載入搖桿的紋理圖片

		this.mEngine.getTextureManager().loadTextures(this.mTexture, this.mOnScreenControlTexture);
	}


onLoadScene()方法,關鍵的業務邏輯便在該方法中:

public Scene onLoadScene() {
		this.mEngine.registerUpdateHandler(new FPSLogger());

		final Scene scene = new Scene(1);
		scene.setBackground(new ColorBackground(0.09804f, 0.6274f, 0.8784f));

		final int centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
		final int centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;
		final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion);

		scene.getTopLayer().addEntity(face);

//-------------------------------------------以下為左搖桿的實現----------------------------------------------------------------------																final int x1 = 0;													//y座標為螢幕的高度減去搖桿底盤的高度,注意螢幕在前面已經被強制橫屏
		final int y1 = CAMERA_HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight();																				//AnalogOnScreenControl構造方法中:第一第二引數是該搖桿的座標,第三個引數為上面定義camera,第四第五個引數為搖桿底盤和搖桿的紋理區域,第六個引數為pTimeBetweenUpdates介面的更新
		final AnalogOnScreenControl velocityOnScreenControl = new AnalogOnScreenControl(x1, y1, this.mCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, new IAnalogOnScreenControlListener() {											//備註1
			@Override
			public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
				Log.i("test","x1:"+x1+",y1:"+y1+",pValueX:"+pValueX+",pValueY:"+pValueY);
				face.setVelocity(pValueX * 100, pValueY * 100);	//備註2
			}

			@Override
			public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {	//備註3
				/* Nothing. */
			}
		});
		velocityOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);											//備註4
		velocityOnScreenControl.getControlBase().setAlpha(0.5f);

		scene.setChildScene(velocityOnScreenControl);
//-------------------------------------------------------end 坐搖桿的實現------------------------------------------------------------//-------------------------------------------------------以下為右搖桿的實現----------------------------------------------------------

		final int y2 = (this.mPlaceOnScreenControlsAtDifferentVerticalLocations) ? 0 : y1;
		final int x2 = CAMERA_WIDTH - this.mOnScreenControlBaseTextureRegion.getWidth();
		final AnalogOnScreenControl rotationOnScreenControl = new AnalogOnScreenControl(x2, y2, this.mCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, new IAnalogOnScreenControlListener() {
			@Override
			public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
				Log.i("test","x2:"+x2+",y2:"+y2+",pValueX:"+pValueX+",pValueY:"+pValueY);
				if(pValueX == x1 && pValueY == x1) {
					face.setRotation(x1);
				} else {
					face.setRotation(MathUtils.radToDeg((float)Math.atan2(pValueX, -pValueY)));	
								//備註5
				}
			}

			@Override
			public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
				/* Nothing. */
			}
		});
		rotationOnScreenControl.getControlBase().setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		rotationOnScreenControl.getControlBase().setAlpha(0.5f);

		velocityOnScreenControl.setChildScene(rotationOnScreenControl);		//備註6

		return scene;
	}														//---------------------------------------------end 右搖桿的實現------------------------------------------------------------

備註1:關於AnalogOnScreenControl 類的第六個引數pTimeBetweenUpdates,我在這裡把他理解成介面的延時程度,值設的越高,則精靈跟隨搖桿變換的越緩慢;但是如果設成0,則兩個搖桿失靈,於是我們在這裡把他設定成0.1f,便可以看到精靈跟隨搖桿很靈活的變換而沒有卡殼和延時的現象

備註2:face.setVelocity,整個精靈移動的核心程式碼便是這一句,怎麼樣?比起用SurfaceView實現的搖桿簡單方便的多吧!

備註3:onControlClick(),這個方法是當我們點選搖桿的時候會觸發的方法,比如我們在這裡可以把搖桿設定放大1.5倍,當沒有點選的時候又恢復原來的狀態,給人一種真實的感覺。

備註5:face.setRotation(),精靈的轉動也是這一句程式碼便可實現,MathUtils.radToDeg方法返回的是:(180/PI)*方法中的引數; Math.atan2()函式返回點(x,y)和原點(0,0)之間直線的傾斜角。具體可以參考http://apps.hi.baidu.com/share/detail/50270911

備註6:這裡可能會有疑問,為什麼是velocityOnScreenControl.setChildScene,而不是scene.setChildScene,事實上,經過測試發現,scene.setChildScene這種情況會把前面定義好的左邊的搖桿覆掉,也就沒有了,scene只會顯示最後一個定義的搖桿,於是我們在這裡寫好的右邊的搖桿需要setChildScene左邊的搖桿中,然後一起setChildScene整個場景中,這樣兩個搖桿都會顯示了。