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

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的小游戏打飞机(三)添加敌机

时间: 2024-10-05 19:21:11

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

第三十九天 一乐在其中—Android的小游戏打飞机(三)飞机打子弹

8月7日,小雨."乳鸦啼散玉屏空,一枕新凉一扇风.睡起秋色无觅处,满阶梧桐月明中." 上篇已经让飞机随手指自由移动,本篇加载子弹和音效及背景音乐. 本篇要用到的几个函数讲解: 一.cocos2d的音效.背景音乐函数如下: 1.SoundEngine.sharedEngine().playSound(Context ctxt, int resId, boolean loop) 用于播放背景音乐. 2.SoundEngine.sharedEngine().playEffect(Contex

第三十八天 一乐在其中—Android的小游戏打飞机(二)移动飞机

8月6日,阴."桑条无叶土生烟,箫管迎龙水庙前.朱门几处看歌舞,犹恐春阴咽管弦". 上篇已经把飞机放到了屏幕上,怎么让飞机随手指自由移动,是本篇解决的问题. 本篇要用到的几个函数讲解: 一.cocos2d的触摸事件如下: 1.ccTouchesMoved:接受的是手指在屏幕上滑动/停留的信息,即当用户手指在屏幕移动时,执行该方法. 2.ccTouchesBegan:接受的是手指点击屏幕的那一下的信息,即当用户开始触摸屏幕时,执行该方法. 3.ccTouchesEnded: 接受手指离开

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

8月10日,晴."寒蝉凄切,对长亭晚,骤雨初歇." 上篇已经加载了敌机,本篇主要添加背景画面. 本篇要用到的几个函数讲解: 1.addChild(CCNode child, int z):两个参数,第一个要加入场景的对象,第二个是绘制层的顺序,默认参数值为0,表示最高优先层导入,该值越大表示该层在最后加载(在最高一层),一般背景图层是首先加载,其它元素在加载在背景层上面.因为背景在后面加载的话,会覆盖掉前面加载的元素,看不到想要的图层组合效果. 2.schedule(String se

第三十七天 一乐在其中—Android的小游戏打飞机(一)

8月3日,晴天."绿树阴浓夏日长,楼台倒影入池塘, 水晶帘动微风起,满架蔷薇一院香." cocos2d是一个开源的游戏开发框架,利用它可以非常容易的开发2D游戏.目前最主要的分支是iPhone版本的,你可以在iPhone上开发2D游戏.它提供了物理,精灵(sprites),视差卷轴(parallax scrolling),支持iPhone touch和accelerator等很多功能.现在在App Store上已经有不少用cocos2d开发的游戏. 如果你想在Andriod上使用Jav

第三十七天 一乐在当中—Android的小游戏打飞机(一)环境搭建

8月3日,晴天."绿树阴浓夏日长.楼台倒影入池塘. 水晶帘动微风起,满架蔷薇一院香. " cocos2d是一个开源的游戏开发框架.利用它能够非常easy的开发2D游戏.眼下最基本的分支是iPhone版本号的,你能够在iPhone上开发2D游戏. 它提供了物理.精灵(sprites).视差卷轴(parallax scrolling),支持iPhone touch和accelerator等非常多功能.如今在App Store上已经有不少用cocos2d开发的游戏. 假设你想在Andriod

android 小游戏 ---- 数独(三)

segment 3 android 小游戏 ----  数独(三) 好的,既然要把数独棋盘中初始提示数字绘制出来,我们就要先了解数独的一些特点. 数独棋盘中总共是81个数字,那我们是否可以用一个数组来代表整个棋盘对应的数字呢想象我们初始化一个9x9的数组,private int[] sudoku = new int[9*9] //初始化数据 private int[] sudoku = new int[9*9]; 这里使用一维数组,当然使用二维数组更加明了直接,这个随个人喜好. 那么我们可以让

第四十六讲:Android之Dialog 对话框(三)

驾驭命运的舵是奋斗.不抱有一丝幻想,不放弃一点机会,不停止一日努力. 本讲内容:Dialog 对话框 例六:信息内容是一组简单列表项 下面是MainActivity.java主界面文件: public class MainActivity extends Activity{ private Button b; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSta

猫猫学iOS(四十五)之常用的小功能比如打电话、打开网址、发邮件、发短信打开其他应用。

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243?viewmode=contents 简介 iOS中的很多小功能都是非常简单的,几行代码就搞定了,比如打电话.打开网址.发邮件.发短信.打开其他应用等. 打电话 方法1 最简单最直接的方式:直接跳到拨号界面 NSURL *url = [NSURL URLWithString:@"tel://10010"]; [[UIApplication sharedA

测开之路四十九:用Django实现扑克牌游戏

用Django实现和之前flask一样的扑克牌游戏 项目结构 html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>扎金花</title></head><body> {% for poker in player1 %} <img src="/static/poker