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);
}
} }

      
三、
执行结果



           源码下载地址:http://download.csdn.net/detail/zwszws/7734537

版权声明:本文博客原创文章,博客,未经同意,不得转载。

第四十天 阿乐在其中—Android小游戏的飞机(四)加入敌人的更多相关文章

  1. android小游戏模版—重力感应

               好久没更新博客了,今天来谈谈android小游戏---重力感应,一般在游戏里运用的比較多,比方这类游戏有:神庙逃亡.极品飞车,平衡球.三围重力迷宫,重力赛车等. 首先什么是重力感 ...

  2. 微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)

    微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞 ...

  3. 微信小游戏 demo 飞机大战 代码分析 (三)(spirit.js, animation.js)

    微信小游戏 demo 飞机大战 代码分析(三)(spirit.js, animation.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码 ...

  4. 微信小游戏 demo 飞机大战 代码分析 (二)(databus.js)

    微信小游戏 demo 飞机大战 代码分析(二)(databus.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码分析(三)(spirit. ...

  5. 微信小游戏 demo 飞机大战 代码分析 (一)(game.js, main.js)

    微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码分析(二)(databus.js) 微信小游戏 demo 飞机大战 代码分析(三)(spirit. ...

  6. Android开发系列(十六):【Android小游戏成语连连看】第二篇

    写的晚了,在分工个Z市高中的一个成绩查询的系统,原系统居然是用VB写的,我不得不佩服原本写系统的那位哥们真能耐得住. 明天搭建下SVN就等着先发project款然后開始项目了.想想有工资进账,心里也为 ...

  7. Android开发系列(十五):【Android小游戏成语连连看】第一篇

            学了一个多月安卓.由于暑假的时候要给朋友说写个小游戏.并且也想检測下自己的能力,所以说从7号開始就着手写这个小游戏了,前前后后带上课到今天总算是写完了,可是写的这个小游戏还是有非常多问 ...

  8. 软件工程 Android小游戏 猜拳大战

    一.前言 最近学校举办的大学生程序设计竞赛,自己利用课余时间写了一个小游戏,最近一直在忙这个写这个小游戏,参加比赛,最终是老师说自己写的简单,可以做的更复杂的点的.加油 二.内容简介 自己玩过Andr ...

  9. 介绍一款Android小游戏--交互式人机对战五子棋

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6589025 学习Android系统开发之余,编 ...

随机推荐

  1. swift学习第十天:函数

    函数的介绍 函数相当于OC中的方法 函数的格式如下 func 函数名(参数列表) -> 返回值类型 { 代码块 return 返回值 } func是关键字,多个参数列表之间可以用逗号(,)分隔, ...

  2. “locktype”enum type 类型重定义问题的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 使用ado来连接数据库,结果出现这样一些编译错误: 1>f:\c++pro\iocptser\debug\msa ...

  3. php-post模拟登录,同步登录(摘自网络)

    这也是个老生常谈的话题了,上午花了点时间把这个问题整理了一下. 一般来说用PHP来模拟post提交数据有三种方法,file_get_contents.curl和socket. 写了个公用函数,专门用来 ...

  4. android使用Gson来解析json

    Gson是一种对象的解析json,非常好用,介绍一个站点http://json.parser.online.fr/能够帮我们看一个字符串是不是Json 对于Json文件 { "id" ...

  5. c++11之初始化列表

    一.前言     C++的学习中.我想每一个人都被变量定义和申明折磨过,比方我在大学笔试过的几家公司.都考察了const和变量,类型的不同排列组合,让你差别有啥不同.反正在学习C++过程中已经被折磨惯 ...

  6. [React Router v4] Style a Link that is Active with NavLink

    We often need to be able to apply style to navigation links based on the current route. In React Rou ...

  7. 日志报错Can't add self as subview

    #pragma mark- add 20151112 导航动画时间太短导致崩溃,重写UINavigationcontroller以下相关方法 - (id)navigationLock; ///< ...

  8. 怎么实现登录之后跳转到登录之前的页面?SpringMVC+Freemarker

    项目中,想实现一个功能. 直接访问某个需要登录的url,比如/addArticle,可能会跳转到登录页面login.html. 登录成功之后,自动跳转到/addArticle这个登录前的页面,继续登录 ...

  9. sparksql json 合并json数据

    java public class Demo { private static SparkConf conf = new SparkConf().setAppName("demo" ...

  10. 不要放弃使用border-box

    不知道有多少老前端像我这样,在项目中很少使用box-sizing这个属性值.因为CSS2.1中只有content-box这一种盒子模式,在CSS3还没有流行的时候,大家在工作中大量基于这种盒子模式写C ...