1.程序主界面:
屏幕有猎枪,每一轮5发子弹,游戏可以一直玩下去。通过晃动手机,可以重力加速度传感器控制准星和猎枪角度的移动。为了增加啊趣味性,同时增加了小鸟移动的场景,白云也是可以移动的。
2在游戏开始的过程中,可以点击返回键暂停游戏。
下面从源码角度以及代码功能角度讲解一下快乐打小鸟的游戏。
首先,游戏含有5部分,移动的小鸟,移动的云,小鸟散落的羽毛,游戏相关的场景布局和设置以及射击小鸟部分。下面将分别对这5各部分进行介绍。
(1) 移动的小鸟。
关于小鸟的各种属性设置其实在bird.java文件中,在eclipse中的目录文件层次结构如下图所示:
Bird有以下几种状态,下落状态,已下落,正在飞行,已经飞走,是否受惊吓(枪声),小鸟的速度。分别对应如下几个属性:
private boolean falling = false; //下落状态
private boolean fallen = false; //已落下
private boolean flying = true; //正在飞
private boolean flyAway = false; //已经飞走
private boolean wasScared = true; //是否受惊吓
private int deadRotation = 0; //死亡时旋转角度
private float xSpeed = 1, ySpeed = 0;
private int speed = 4; //速度
private Random r = new Random();
private final long creationTime;
private long pauseTime=0;
private final long lifeTime = 30*1000;//存活时间,默认30 secs
调用update函数可以对小鸟的各种状态进行更新,从而在画面上实时显示,达到动态的效果。
public void update()
{
float currX = getX();
float currY = getY();
if(System.currentTimeMillis() - creationTime-pauseTime > lifeTime && isFlying())
{
setFlyAway(true);
}
if(flying)
{
if(wasScared)
{
ySpeed=-ySpeed;
wasScared = false;
}
currX =currX + speed * xSpeed;
if(currX<0)
{
currX= 0;
getTextureRegion().setFlippedHorizontal(!getTextureRegion().isFlippedHorizontal());
xSpeed=-xSpeed;
}
else if(currX+getWidth()>ShotBirdGame.CAMERA_WIDTH)
{
currX= ShotBirdGame.CAMERA_WIDTH-getWidth();
getTextureRegion().setFlippedHorizontal(!getTextureRegion().isFlippedHorizontal());
xSpeed=-xSpeed;
}
currY =currY + speed * ySpeed;
if(currY<0)
{
currY= 0;
ySpeed=-ySpeed;
}
else if(currY+getHeight()>ShotBirdGame.CAMERA_HEIGHT-ShotBirdGame.grass.getHeight())
{
currY= ShotBirdGame.CAMERA_HEIGHT-ShotBirdGame.grass.getHeight()-getWidth();
ySpeed=-ySpeed;
}
int rotCoeff = 1;
if(xSpeed>0)
{
rotCoeff= 1;
}
else
{
rotCoeff= -1;
}
if(ySpeed>0)
{
setRotation(15*rotCoeff);
}
else
{
setRotation(-15*rotCoeff);
}
setPosition(currX,currY);
}
else if(flyAway)
{
ySpeed =Math.abs(ySpeed)*-1;
currX =currX + speed * xSpeed*2;
currY =currY + speed * ySpeed*2;
if(currX+getWidth()<0)
{
fallen = true;
}else if(currX>ShotBirdGame.CAMERA_WIDTH)
{
fallen = true;
}
if(currY+getHeight()<0)
{
fallen = true;
}
int rotCoeff = 1;
if(xSpeed>0)
{
rotCoeff= 1;
}
else
{
rotCoeff= -1;
}
setRotation(-15*rotCoeff);
setPosition(currX,currY);
}
else if (falling)
{
currX =currX + 2 * xSpeed;
if(currX+getWidth()<0)
{
currX= ShotBirdGame.CAMERA_WIDTH;
}else if(currX>ShotBirdGame.CAMERA_WIDTH)
{
currX= 0-getWidth();
}
currY+=10;
if(currY > ShotBirdGame.CAMERA_HEIGHT-ShotBirdGame.grass.getHeight())
{
currY= ShotBirdGame.CAMERA_HEIGHT-ShotBirdGame.grass.getHeight();
fallen = true;
falling = false;
}
setPosition(currX,currY);
deadRotation += 5*xSpeed;
setRotation(deadRotation);
}
}
(2) 移动的云。
为了是游戏的画面感更具动态性,增加了移动的云朵。云朵主要含有速度这一个属性,对应的class文件为Cloud.java。其中定时对云朵的状态进行更新,可以达到动态的效果。更新状态的功能主要如下:
//更新云朵的位置信息
public void update()
{
float currX = getX() + cloudSpeed;
if(currX+getWidth()<0)
{
currX =ShotBirdGame.CAMERA_WIDTH;
}else if(currX>ShotBirdGame.CAMERA_WIDTH)
{
currX =0-getWidth();
}
setPosition(currX,getY());
}
(3) 散落的羽毛。
散落的羽毛主要是在小鸟被子弹打中时出现,含有动态的散落的效果。主要对应的是class文件为Feather.java文件。更新羽毛所在的位置信息的代码如下:
//更新羽毛所在的位置信息
public void update()
{
if(System.currentTimeMillis()-creationTime<lifeTime)
{
if(random.nextBoolean())
{
setPosition(getX()+random.nextInt(10), getY()+1);
}
else
{
setPosition(getX()+random.nextInt(10)*-1, getY()+1);
}
}
else
{
dead = true;
}
}
(4)快乐打小鸟游戏的主要部分。
这部分包含应用程序的入口,已经游戏所需资源文件的一些初始化操作。游戏场景的加载和游戏中涉及的对象的初始化。比如山,陆地,草坪,小的云朵,射击的音效等。加载UI元素的代码如下:
private final int add = 50;
protected static final String PREFS_NAME = "GAME_SETTINGS";
protected static final String USE_SOUND = "SOUND";
protected static final String USE_VIBRO = "VIBRO";
protected static final String USE_ACC = "ACC";
protected static final String USE_TOUCH = "TOUCH";
public static int CAMERA_WIDTH = 800;//480;
public static int CAMERA_HEIGHT = 480;//320;
private Camera mCamera;
private Texture mTexture,mTexture2,mTexture3;
public static TextureRegion /*background,*/
hills,
sky,
largeCloud,
mediumCloud,
smallCloud,
grass,
aim,
barrel,
feather,
featherFlipped,
shootbutton,
shell,
flash,
shot,
logo,
startButton,
settingsButton;
public static TiledTextureRegion birdFly,birdFlyFlipped;
public static Sound sShotReload;
public static Font mDuckFont;
public static Texture mDuckFontTexture;
private Game game;
private boolean musicPaused;
本游戏主要用到了andengine游戏开发引擎,加载游戏引擎的带阿妈如下(其中本游戏的最小分辨率是320X480,最佳分辨率是480x800):
//加载游戏引擎
public Engine onLoadEngine() {
Displaydisplay = getWindowManager().getDefaultDisplay();
CAMERA_WIDTH = display.getWidth();
CAMERA_HEIGHT = display.getHeight();
if(CAMERA_WIDTH<=480 && CAMERA_HEIGHT<=320)
{
CAMERA_WIDTH=480;
CAMERA_HEIGHT=320;
}
this.mCamera = new Camera(0,0,CAMERA_WIDTH,CAMERA_HEIGHT);
return new Engine(newEngineOptions(true,ScreenOrientation.LANDSCAPE,new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT),this.mCamera).setNeedsSound(true).setNeedsMusic(true));
}
加载游戏所用的所有资源:
//加载游戏所需的资源
public void onLoadResources() {
Log.i("WIDTHxHEIGHT", CAMERA_WIDTH+"x"+CAMERA_HEIGHT);
if(CAMERA_WIDTH<=480 && CAMERA_HEIGHT<=320)
{
this.mTexture = newTexture(1024,1024,TextureOptions.BILINEAR);
ShotBirdGame.hills = TextureRegionFactory.createFromAsset(this.mTexture, this, "graphics/background480hills.png",0,0);
ShotBirdGame.sky = TextureRegionFactory.createFromAsset(this.mTexture, this, "graphics/background480sky.png",0,306);
ShotBirdGame.grass= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/background480grass.png",0,642);
ShotBirdGame.barrel= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/barrel480.png",802,0);
ShotBirdGame.aim= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/crosshairs480.png",802,352);
ShotBirdGame.birdFly = TextureRegionFactory.createTiledFromAsset(this.mTexture, this,"graphics/birdallframes480.png",0,642+82,4,4);
ShotBirdGame.birdFlyFlipped = birdFly.clone();
ShotBirdGame.birdFlyFlipped.setFlippedHorizontal(true);
ShotBirdGame.shell= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/shell480.png",322,642+82);
ShotBirdGame.shootbutton= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/shootbutton480.png",322+50,642+82);
ShotBirdGame.feather = TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/feather.png",0,642+82+256);
ShotBirdGame.featherFlipped = feather.clone();
ShotBirdGame.featherFlipped.setFlippedHorizontal(true);
this.mEngine.getTextureManager().loadTexture(this.mTexture);
//no enough space in mTexture left :)
this.mTexture2 = newTexture(1024,1024,TextureOptions.BILINEAR);
ShotBirdGame.largeCloud = TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/largecloud.png",0,0);
ShotBirdGame.mediumCloud = TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/mediumcloud.png",242,0);
ShotBirdGame.smallCloud = TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/smallcloud.png",242+130,0);
ShotBirdGame.flash= TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/muzzleflash480.png",0,66);
ShotBirdGame.shot= TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/shot480.png",98,66);
this.mEngine.getTextureManager().loadTexture(this.mTexture2);
this.mTexture3 = newTexture(1024,1024,TextureOptions.BILINEAR);
ShotBirdGame.logo = TextureRegionFactory.createFromAsset(this.mTexture3, this, "graphics/title480.png",0,0);
ShotBirdGame.startButton = TextureRegionFactory.createFromAsset(this.mTexture3, this, "graphics/startbutton.png",0,226);
ShotBirdGame.settingsButton = TextureRegionFactory.createFromAsset(this.mTexture3, this, "graphics/settingsbutton.png",0,226+50);
this.mEngine.getTextureManager().loadTexture(this.mTexture3);
ShotBirdGame.mDuckFontTexture = new Texture(256,256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
FontFactory.setAssetBasePath("font/");
ShotBirdGame.mDuckFont = FontFactory.createFromAsset(ShotBirdGame.mDuckFontTexture, this, "comixheavy.ttf", 28, true, Color.BLACK);
this.mEngine.getTextureManager().loadTexture(ShotBirdGame.mDuckFontTexture);
this.mEngine.getFontManager().loadFont(ShotBirdGame.mDuckFont);
}
else
{
this.mTexture = newTexture(1024,1024,TextureOptions.BILINEAR);
ShotBirdGame.hills = TextureRegionFactory.createFromAsset(this.mTexture, this, "graphics/background800hills.png",0,0);
ShotBirdGame.sky = TextureRegionFactory.createFromAsset(this.mTexture, this, "graphics/background800sky.png",0,306+add);
ShotBirdGame.grass= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/background800grass.png",0,642+add);
ShotBirdGame.barrel= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/barrel800.png",802+add,0);
ShotBirdGame.aim= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/crosshairs800.png",802+add,352);
ShotBirdGame.birdFly = TextureRegionFactory.createTiledFromAsset(this.mTexture, this,"graphics/birdallframes800.png",0,642+82+add*4/5,4,4);
ShotBirdGame.birdFlyFlipped = birdFly.clone();
ShotBirdGame.birdFlyFlipped.setFlippedHorizontal(true);
ShotBirdGame.shell= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/shell800.png",322,642+82+add);
ShotBirdGame.shootbutton= TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/shootbutton800.png",322+50,642+82+add);
ShotBirdGame.feather = TextureRegionFactory.createFromAsset(this.mTexture, this,"graphics/feather.png",0,642+82+256);
ShotBirdGame.featherFlipped = feather.clone();
ShotBirdGame.featherFlipped.setFlippedHorizontal(true);
this.mEngine.getTextureManager().loadTexture(this.mTexture);
//no enough space in mTexture left :)
this.mTexture2 = newTexture(1024,1024,TextureOptions.BILINEAR);
ShotBirdGame.largeCloud = TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/largecloud.png",0,0);
ShotBirdGame.mediumCloud = TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/mediumcloud.png",242+add,0);
ShotBirdGame.smallCloud = TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/smallcloud.png",242+130+add,0);
ShotBirdGame.flash= TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/muzzleflash800.png",0,66);
ShotBirdGame.shot= TextureRegionFactory.createFromAsset(this.mTexture2, this, "graphics/shot800.png",98,66);
this.mEngine.getTextureManager().loadTexture(this.mTexture2);
this.mTexture3 = newTexture(1024,1024,TextureOptions.BILINEAR);
ShotBirdGame.logo = TextureRegionFactory.createFromAsset(this.mTexture3, this, "graphics/title800.png",0,0);
ShotBirdGame.startButton = TextureRegionFactory.createFromAsset(this.mTexture3, this, "graphics/startbutton.png",0,226+add);
ShotBirdGame.settingsButton = TextureRegionFactory.createFromAsset(this.mTexture3, this, "graphics/settingsbutton.png",0,226+50+add);
this.mEngine.getTextureManager().loadTexture(this.mTexture3);
ShotBirdGame.mDuckFontTexture = new Texture(256,256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
FontFactory.setAssetBasePath("font/");
ShotBirdGame.mDuckFont = FontFactory.createFromAsset(ShotBirdGame.mDuckFontTexture, this, "comixheavy.ttf", 48, true, Color.BLACK);
this.mEngine.getTextureManager().loadTexture(ShotBirdGame.mDuckFontTexture);
this.mEngine.getFontManager().loadFont(ShotBirdGame.mDuckFont);
}
SoundFactory.setAssetBasePath("sounds/");
MusicFactory.setAssetBasePath("sounds/");
try {
ShotBirdGame.sShotReload = SoundFactory.createSoundFromAsset(this.mEngine.getSoundManager(), this, "gunshotreload.ogg");
} catch (final IOException e) {
Debug.e("Error", e);
}
}
(4) Game也是本游戏中很重要的一个类,仅次于ShotBirdGame类,主要是游戏中场景对象的一些控制,游戏画面的更新等。Game类中定义了一些基本的属性,比如每一轮子弹数量的多少(一般为5发),云朵数量的最大值,更新数据的时间,手机返回键的获取,游戏状态的设置(开始,暂停,继续)等。其属性信息如下:
private int GAME_STATE;
public static final int STATE_MENU=0;
public static final int STATE_RUN=1;
public static final int STATE_DIALOGS=2;
private Random random = new Random();
private ArrayList<Bird> birds = new ArrayList<Bird>();
private ArrayList<Bird> birdsToRemove = new ArrayList<Bird>();
private ArrayList<Feather> feathers = new ArrayList<Feather>();
private ArrayList<Feather> feathersBuffer = new ArrayList<Feather>();
private ArrayList<Feather> feathersToRemove = new ArrayList<Feather>();
private ArrayList<Cloud> clouds = new ArrayList<Cloud>();
private int maxClouds = 5;
private Sprite grass, /*background,*/shootbutton,hills,sky;
private Sprite aim;
private float aimXSpeed = 0;
private float aimYSpeed = 0;
private Sprite barrel;
private Sprite flash;
private Sprite shot;
private int shells=5;
private boolean updateShells = false;
private ArrayList<Sprite> shellSprites = new ArrayList<Sprite>();
private boolean roundOver = false;
private final int birdsLeft = 1000;
private int birdsCreated = 0;
private float birdSpeed = 0.6f;
private Text nextLevelMsg;
private Scene gameScene;
射击小鸟的函数主要代码如下:
private void makeShoot() {
if(useSound)ShotBirdGame.sShotReload.play();
flash.setAlpha(1.0f);
shot.setPosition(aim.getX()+aim.getWidth()/2-shot.getWidth()/2, aim.getY()+aim.getHeight()/2-shot.getHeight()/2);
shot.setAlpha(1.0f);
//
for(final Bird bird: birds)
{
if(bird.isFlying() && aim.collidesWith(bird))
{
//如果子弹碰到小鸟,小鸟会死
float birdCenterX =bird.getX()+bird.getWidth()/2;
float birdCenterY =bird.getY()+bird.getHeight()/2;
float shotCenterX =shot.getX()+shot.getWidth()/2;
float shotCenterY =shot.getY()+shot.getHeight()/2;
if(BaseCollisionChecker.checkAxisAlignedRectangleCollision(
birdCenterX-bird.getWidth()*0.6f/2,
birdCenterY-bird.getHeight()*0.6f/2,
birdCenterX+bird.getWidth()*0.6f/2,
birdCenterY+bird.getHeight()*0.6f/2,
shotCenterX-shot.getWidth()*0.9f/2,
shotCenterY-shot.getHeight()*0.9f/2,
shotCenterX+shot.getWidth()*0.9f/2,
shotCenterY+shot.getHeight()*0.9f/2))
{
bird.setFalling(true);
bird.stopAnimation(12);
synchronized (feathersBuffer) {
for(int i=0;i<10;i++)
{
float featherSize = 1+(1+random.nextInt(9))/10;
//first bird
Featherfeather;
if(random.nextBoolean())
{
feather= newFeather(bird.getX()-bird.getWidth()*featherSize/2+random.nextInt((int) (bird.getWidth())),
bird.getY()-bird.getHeight()*featherSize/2+random.nextInt((int) (bird.getHeight()))/*random.nextInt(320-40grass*/,
ShotBirdGame.feather.getWidth()*featherSize,
ShotBirdGame.feather.getHeight()*featherSize,ShotBirdGame.feather);
}
else
{
feather= new Feather(/*-20*/bird.getX()-bird.getWidth()*featherSize/2+random.nextInt((int) (bird.getWidth())),
bird.getY()-bird.getHeight()*featherSize/2+random.nextInt((int) (bird.getHeight()))/*random.nextInt(320-40grass*/,
ShotBirdGame.featherFlipped.getWidth()*featherSize,
ShotBirdGame.featherFlipped.getHeight()*featherSize,ShotBirdGame.featherFlipped);
}
feathersBuffer.add(feather);
gameScene.getLayer(1).addEntity(feather);
}
}
break;
}
else
{
bird.setWasScared(true);
bird.animate(new long[]{100,100,100,100}, 8, 11, 4,new IAnimationListener()
{
public void onAnimationEnd(
AnimatedSpriteanimatedSprite) {
bird.animate(new long[]{100,100,100,100}, 0, 3, true);
}
});
}
}
}
shells--;//子弹数量减一
if(shells<0)
{
shells=0;//如果没有子弹了,子弹数量为0
}
updateShells = true;
if(birds.size()>0 && shells == 0)
{
roundOver = true;
}
}
更新游戏状态信息:
public void update() {
if(!loadComplete)//游戏是否加载完成
{
loadComplete = true;
gameActivity.hideScoreLoop(false,true);
}
{
for (Cloud cloud : clouds) {
cloud.update();
}
}
if(GAME_STATE == STATE_RUN && !paused)
{
updateCrosshair();
updateFeathers();
if(updateShells)
{
updateShellsIndicator();
updateShells = false;
}
if(birds.size() == 0 )
{
if(birdsCreated<birdsLeft)
{
//第一只鸟
Birdbird = new Bird(0, random.nextInt((int) (grass.getY()-grass.getHeight())),
ShotBirdGame.birdFly.getTileWidth(),
ShotBirdGame.birdFly.getTileHeight(),ShotBirdGame.birdFly,useSound);
birds.add(bird);
gameScene.getLayer(1).addEntity( bird);
bird.setXSpeed(birdSpeed);
ShotBirdGame.birdFly.setFlippedHorizontal(false);
bird.animate(new long[]{100,100,100,100}, 0, 3, true);
//第二只鸟飞向另一边
bird= new Bird(ShotBirdGame.CAMERA_WIDTH-ShotBirdGame.birdFlyFlipped.getTileWidth(), random.nextInt((int) (grass.getY()-grass.getHeight())),
ShotBirdGame.birdFlyFlipped.getTileWidth(),
ShotBirdGame.birdFlyFlipped.getTileHeight(),ShotBirdGame.birdFlyFlipped,useSound);
birds.add(bird);
bird.setXSpeed(-birdSpeed);
gameScene.getLayer(1).addEntity(bird);
ShotBirdGame.birdFlyFlipped.setFlippedHorizontal(true);
bird.animate(new long[]{100,100,100,100}, 0, 3, true);
shells = 5;
updateShells = true;
birdsCreated+=2;
}
}
else
{
for (Bird bird : birds) {
if(roundOver && !bird.isFalling() && !bird.isFallen())
{
bird.setFlyAway(true);
}
bird.update();
if(bird.isFallen())
{
birdsToRemove.add(bird);
}
}
roundOver = false;
for(Bird bird: birdsToRemove)
{
birds.remove(bird);
gameScene.getLayer(1).removeEntity(bird);
}
birdsToRemove.clear();
}
}
else if(GAME_STATE == STATE_MENU)
{
if(birds.size()>0)
{
for(Bird bird:birds)
{
gameScene.getLayer(1).removeEntity(bird);
}
birds.clear();
}
if(feathers.size()>0)
{
for(Feather feather:feathers)
{
gameScene.getLayer(1).removeEntity(feather);
}
feathers.clear();
}
if(feathersBuffer.size()>0)
{
for(Feather feather:feathersBuffer)
{
gameScene.getLayer(1).removeEntity(feather);
}
feathersBuffer.clear();
}
}
}
对获取的加速度计的数值进行处理,从而通过调整手机的姿态信息达到调整猎枪准心角度的目的。监听加速度计数值变化的代码如下:
public void onAccelerometerChanged(AccelerometerDataaccelerometerData) {
if(accelerometer){
aimYSpeed = (accelerometerData.getX()-5)*2;
if(aimYSpeed>0)aimYSpeed*=1.5f;
aimXSpeed = accelerometerData.getY()*3;
}
}
没开枪一下,更新子弹数量的指示器函数的代码如下:
public void updateShellsIndicator()
{
float shellOffset = 0;
while (shells<shellSprites.size()) {
gameScene.getLayer(2).removeEntity(shellSprites.get(0));
shellSprites.remove(0);
}
for(int i=0;i<shells;i++)
{
Spriteshell;
if(i+1>shellSprites.size()){
shell= new Sprite(ShotBirdGame.shell.getWidth()/2 + shellOffset,ShotBirdGame.CAMERA_HEIGHT-ShotBirdGame.shell.getHeight()*1.5f,ShotBirdGame.shell.getWidth(),ShotBirdGame.shell.getHeight(),ShotBirdGame.shell);
gameScene.getLayer(2).addEntity(shell);
shellSprites.add(shell);
}
else
{
shell= shellSprites.get(i);
shell.setPosition(ShotBirdGame.shell.getWidth()/2 + shellOffset, shell.getY());
}
shellOffset+= shell.getWidth();
}
}
更新猎枪的准心状态的显示函数主要如下:
public void updateCrosshair()
{
aim.setPosition(aim.getX() + aimXSpeed, aim.getY()+aimYSpeed);
if(aim.getY()+aim.getHeight()/2>grass.getY())
{
aim.setPosition(aim.getX(),grass.getY()-aim.getHeight()/2);
}
else if(aim.getY()+aim.getHeight()/2<0)
{
aim.setPosition(aim.getX(),0-aim.getHeight()/2);
}
if(aim.getX()+aim.getWidth()/2>ShotBirdGame.CAMERA_WIDTH)
{
aim.setPosition(ShotBirdGame.CAMERA_WIDTH-aim.getWidth()/2,aim.getY());
}
else if(aim.getX()+aim.getWidth()/2<0)
{
aim.setPosition(0-aim.getWidth()/2,aim.getY());
}
//移动枪的位置
float barrelYOffset = aim.getY()*(barrel.getHeight()*0.2f)/grass.getY();
barrel.setPosition(barrel.getX(),
ShotBirdGame.CAMERA_HEIGHT-barrel.getHeight()/2
+barrelYOffset);
//旋转枪
Vector2 src =new Vector2(barrel.getX()+barrel.getWidth()/2,barrel.getY()+barrel.getHeight()/2);
Vector2 dst =new Vector2(aim.getX()+aim.getWidth()/2, aim.getY()+aim.getHeight()/2);
float angle = (float) (Math.atan2(src.y-dst.y,src.x-dst.x)*180/Math.PI-90);
barrel.setRotation(angle);
//枪射击效果
flash.setPosition(barrel.getX()+barrel.getWidth()/2-flash.getWidth()/2, barrel.getY()-flash.getHeight()/2);
flash.setRotationCenter(flash.getWidth()/2, barrel.getHeight()-flash.getHeight());
flash.setRotation(barrel.getRotation());
if(flash.getAlpha()>0)
{
flash.setAlpha(flash.getAlpha()-0.4f);
if(flash.getAlpha()<0)
{
flash.setAlpha(0);
}
}
if(shot.getAlpha()>0)
{
shot.setAlpha(shot.getAlpha()-0.3f);
if(shot.getAlpha()<0)
{
shot.setAlpha(0);
}
}
if(nextLevelMsg.getAlpha()>0)
{
nextLevelMsg.setAlpha(nextLevelMsg.getAlpha()-0.025f);
if(nextLevelMsg.getAlpha()<0)
{
nextLevelMsg.setAlpha(0);
}
}
}a