第四十天 一乐在其中—Android的小游戏打飞机(四)添加敌机

时间:2021-12-30 14:58:47
          

             8月9日,晴。“江城如画里,山晓望晴空。雨水夹明镜,双桥落彩虹。 人烟寒橘柚,秋色老梧桐。

        上篇已经让飞机加载子弹和音效及背景音乐,本篇主要添加敌机

        本篇要用到的几个函数讲解:

       1、voidsetTag (int nTag) 设置动作的标记。

       2、CCRANDOM_0_1()函数生成的是 [0, 1] 之间的随机数;要生成  [0-100] 之间的数CCRANDOM_0_1 * 100;生成 [1,5]  之间的float 数,就是 CCRANDOM_0_1 * 4 + 1。

       3、sprite.getContentSize 得到精灵的矩形区域宽、高。获得节点原始的大小,只是逻辑尺寸,不是像素。

       float initX = (winSize.width - sprite.getContentSize().width) * ccMacros.CCRANDOM_0_1() + sprite.getContentSize().width/2;

              表示敌机在X轴上的任意位置,sprite.getContentSize().width/2是为了防止出现半个敌机

       
一、
MainActivity.java

package edu.eurasia.cocos2d_game04;

import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.opengl.CCGLSurfaceView;
import org.cocos2d.sound.SoundEngine;

import android.os.Bundle;
import android.app.Activity;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {

// 创建一个view对象,cocos2d引擎会把图形绘制在该view对象上面
private CCGLSurfaceView view = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// 不显示标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 设置当前程序全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// 设置不允许屏幕自动休眠
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

view = new CCGLSurfaceView(this);
setContentView(view);

// 获取导演对象
CCDirector director = CCDirector.sharedDirector();
// 设置游戏引擎画面的输出目标View
director.attachInView(view);
// 设置游戏是否显示FPS值
// director.setDisplayFPS(true);
// 设置游戏的刷新率 FPS = frame per second
director.setAnimationInterval(1 / 60.0f);
// 生成场景对象
CCScene scene = CCScene.node();
// 生成图层对象
PlaneLayer layer = new PlaneLayer(this);
// 将图层添加至场景当中
scene.addChild(layer, 1);
// 通知导演,运行场景
director.runWithScene(scene);
}

@Override
protected void onDestroy() {
super.onDestroy();
//清理所有的音效
SoundEngine.sharedEngine().realesAllSounds();
SoundEngine.sharedEngine().realesAllEffects();
// 完全关闭音响系统
SoundEngine.purgeSharedEngine();
}

}
        二、PlaneLayer.java
package edu.eurasia.cocos2d_game04;

import java.util.ArrayList;
import java.util.List;

import org.cocos2d.actions.instant.CCCallFuncN;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.config.ccMacros;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.sound.SoundEngine;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import org.cocos2d.types.CGSize;

import android.content.Context;
import android.view.MotionEvent;

public class PlaneLayer extends CCLayer {
// 声明一个精灵对象
private CCSprite plane;
private CCDirector director;
private CGSize winSize;
private CGPoint offset;
private boolean flag = false;
// 定义子弹的速度为每秒500像素
private float bulletSpeed = 500;
private Context context;

private List<CCSprite> bullets = new ArrayList<CCSprite>();
private List<CCSprite> enemies = new ArrayList<CCSprite>();

private static final int E1_TAG = 1;
private static final int E2_TAG = 2;

public PlaneLayer(Context context) {
super();
this.context = context;
// 设置当前图层是否接受触摸事件
this.setIsTouchEnabled(true);
director = CCDirector.sharedDirector();
winSize = director.winSize();
// 初始化精灵对象
plane = CCSprite.sprite("p.png");
// 设置精灵对象的位置
plane.setPosition(CGPoint.ccp(winSize.width / 2, 200));
this.addChild(plane);
// 定时器schedule,添加子弹,每隔0.5秒调用一次
schedule("addBullet", 0.5f);
//添加敌人,每隔一秒调用一次
schedule("addEnemy",1f);
// 背景音乐
SoundEngine.sharedEngine().playSound(context, R.raw.game_music, true);
}

// 当用户开始触摸屏幕,执行该方法
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = director.convertToGL(CGPoint.ccp(event.getX(),
event.getY()));
CGRect rect = plane.getBoundingBox();
flag = CGRect.containsPoint(rect, point);

if (flag) {
offset = CGPoint.ccpSub(plane.getPosition(), point);
}

return super.ccTouchesBegan(event);
}

// 当用户手指离开屏幕时,执行该方法
@Override
public boolean ccTouchesEnded(MotionEvent event) {
flag = false;
return super.ccTouchesEnded(event);
}

// 当用户手指在屏幕移动时,执行该方法
@Override
public boolean ccTouchesMoved(MotionEvent event) {
if (flag) {
CGPoint point = director.convertToGL(CGPoint.ccp(event.getX(),
event.getY()));
point = CGPoint.ccpAdd(point, offset);
plane.setPosition(point);
}
return super.ccTouchesMoved(event);
}

public void addBullet(float delta) {
// 生成一个子弹精灵对象
CCSprite bullet = CCSprite.sprite("bullet.png");
// 将子弹对象添加至图层当中
this.addChild(bullet);
// 将新添加的子弹对象放置在bullets集合当中
bullets.add(bullet);

// 获得精灵的大小,getContentSize函数来获得节点原始的大小
CGSize planeSize = plane.getContentSize();
CGSize bulletSize = bullet.getContentSize();

CGPoint initPos = plane.getPosition();
// 子弹的y轴的初始位置
initPos.y = initPos.y + planeSize.height / 2 + bulletSize.height / 2;
bullet.setPosition(initPos);
// 创建一个代表坐标的对象
CGPoint targetPos = CGPoint.ccp(initPos.x, winSize.height);
// 计算两个坐标点之间的距离,计算子弹运行的距离
float distance = CGPoint.ccpDistance(initPos, targetPos);
// 计算子弹运行的时间
float t = distance / bulletSpeed;
// 生成一个动画对象,让子弹移动到屏幕的上端
CCMoveTo moveTo = CCMoveTo.action(t, targetPos);
// 生成一个动作对象,该动作执行时,将会调用当前对象的onBulletMoveToFinished方法
// CCCallFuncN:
// 它可以让你为某个执行此action的对象指定一个回调函数。我们指定的回调函数是:onBulletMoveToFinished
CCCallFuncN func = CCCallFuncN.action(this, "onBulletMoveToFinished");
// CCSequence:
// 它允许我们把一系列的action组成一个action序列,并且这些action可以按顺序执行。一次执行完所有的action。
CCSequence seq = CCSequence.actions(moveTo, func);
// 通知精灵执行动作
bullet.runAction(seq);
// 子弹声效
SoundEngine.sharedEngine().playEffect(context, R.raw.bullet);
}

public void onBulletMoveToFinished(Object sender) {
if (sender instanceof CCSprite) {
CCSprite sprite = (CCSprite) sender;
// 将子弹对象从集合中移除
bullets.remove(sprite);
// 将子弹对象从屏幕中移除
this.removeChild(sprite, true);

}
}

public void addEnemy(float delta){
String imgName = "e1a0.png";
int tag = E1_TAG;
//生成的是 [0, 1] 之间的随机数
float ran = ccMacros.CCRANDOM_0_1();
if(ran > 0.8){
imgName = "e2a0.png";
tag = E2_TAG;
}
//生成代表敌机的精灵对象
CCSprite sprite = CCSprite.sprite(imgName);
// 设置动作的标记
sprite.setTag(tag);
//将敌机添加到当前图层中
this.addChild(sprite);
// 将新添加的敌机对象放置在benemies集合当中
enemies.add(sprite);
//计算敌机的初始化位置
float initY = winSize.height + sprite.getContentSize().height/2;
float initX = (winSize.width - sprite.getContentSize().width) * ccMacros.CCRANDOM_0_1() + sprite.getContentSize().width/2;
//创建一个代表坐标的对象
CGPoint initPos = CGPoint.ccp(initX, initY);
//设置敌机的位置
sprite.setPosition(initPos);
//计算敌机运行的终点位置
float targetX = initX;
float targetY = -sprite.getContentSize().height/2;
//创建一个代表坐标的对象
CGPoint targetPos = CGPoint.ccp(targetX, targetY);
//计算敌机运行的时间
float t = 3 * ccMacros.CCRANDOM_0_1() + 2;
//生成用于移动敌机的MoveTo对象
CCMoveTo moveTo = CCMoveTo.action(t, targetPos);
CCCallFuncN func = CCCallFuncN.action(this, "onEnemyMoveToFinished");
CCSequence seq = CCSequence.actions(moveTo, func);
// 通知精灵执行动作
sprite.runAction(seq);
}

public void onEnemyMoveToFinished(Object sender){
if(sender instanceof CCSprite){
CCSprite sprite = (CCSprite)sender;
//将飞出屏幕的敌机从集合中移除
enemies.remove(sprite);
// 将敌机对象从屏幕中移除
this.removeChild(sprite, true);
}
}

}
      
三、
运行结果

第四十天 一乐在其中—Android的小游戏打飞机(四)添加敌机
           源代码下载地址:http://download.csdn.net/detail/zwszws/7734537