要想制作一款游戏,首先要对它进行分析。
首先分析它的功能:
分析完需求之后,让我们新建一个项目,然后开始着手制作这款游戏吧!
当然,第一步仍然需要导入cocos2d-android.jar包,这样才能让我们以后更好开发,导入jar包后如图所示:
第二步,为了更好的游戏显示效果,推荐修改屏幕的样式为全屏,修改AndroidManifest.xml,如图所示:
第三步,修改MainActivity,直接套用上一个项目里的相关代码,代码如下:
package com.example.zombievsplantdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.opengl.CCGLSurfaceView;
import org.cocos2d.sound.SoundEngine;
public class MainActivity extends AppCompatActivity {
/**
* 导演
*/
CCDirector director = CCDirector.sharedDirector();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//调用顺序:视图(CCGLSurfaceView) -》 导演(CCDirector) -》 场景(CCScene) -》 图层(CCLayer) -》 精灵(CCSprite) -》 动作(CCMove)
// 获取视图
CCGLSurfaceView view = new CCGLSurfaceView(this); // 创建一个SurfaceView,类似导演眼前的小屏幕,必须传this,底层要强转成Actvity
setContentView(view);
// 获取导演的单例对象
director.attachInView(view); // 开启绘制线程的方法
director.setDisplayFPS(true); // 显示帧率,表示每秒刷新页面的次数。一般当帧率大于30帧时,基本上人眼看起来比较流畅,帧率和手机性能与程序性能有关
director.setAnimationInterval(1/60f); // 设置最高帧率位60
director.setDeviceOrientation(CCDirector.kCCDeviceOrientationLandscapeLeft); // 设置屏幕方式为横屏显示
director.setScreenSize(480,320); // 设置分辨率,用于屏幕适配,会基于不同大小的屏幕等比例缩放,设置我们开发时候的分辨率
// 获取场景对象
CCScene scene = CCScene.node();
// 获取图层对象
//FirstLayer layer = new FirstLayer();
//ActionLayer layer = new ActionLayer();
DemoLayer layer = new DemoLayer();
// 配置环境
scene.addChild(layer); // 给场景添加图层
director.runWithScene(scene); // 导演运行场景
}
@Override
protected void onResume() {
super.onResume();
director.resume(); // 游戏继续
SoundEngine.sharedEngine().resumeSound(); // 音乐继续
}
@Override
protected void onPause() {
super.onPause();
director.pause(); // 游戏暂停
SoundEngine.sharedEngine().pauseSound(); // 音乐暂停
}
@Override
protected void onDestroy() {
super.onDestroy();
director.end(); // 游戏结束
}
}
在该类中通过CCDirector.sharedDirector().winSize()
来获取屏幕的宽高,代码如下:package com.example.zombievsplantdemo.layer;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.types.CGSize;
/**
* 基类图层
*/
public class BaseLayer extends CCLayer {
/**
* 屏幕的宽高
*/
public CGSize size = CCDirector.sharedDirector().winSize();
public BaseLayer() {
}
}
package com.example.zombievsplantdemo.layer;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.instant.CCHide;
import org.cocos2d.actions.instant.CCShow;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.nodes.CCSprite;
/**
* 欢迎页面图层
*/
public class WelcomeLayer extends BaseLayer {
/**
* logo对象
*/
private CCSprite logo;
public WelcomeLayer() {
initLogo();// 初始化logo
showLogo(); // 展示logo
}
/**
* 1.logo初始化
*/
private void initLogo(){
logo = CCSprite.sprite("image/popcap_logo.png");
logo.setPosition(size.width / 2 , size.height / 2); // 屏幕居中
this.addChild(logo);
}
/**
* 2.展示logo
*/
private void showLogo(){
CCHide hide = CCHide.action(); // 表示隐藏动作
CCDelayTime delay = CCDelayTime.action(1); // 延时一秒钟
CCShow show = CCShow.action(); // 表示显示动作
CCSequence sequence = CCSequence.actions(hide,delay,show,delay,hide,delay,CCCallFunc.action(this,"showWelcome")); // 一上来先隐藏logo,过一秒后显示logo,再过一秒钟后继续隐藏logo
logo.runAction(sequence);
}
/**
* 3.显示欢迎界面。切记因为用反射调用的该方法,所以访问修饰符一定要是public,这里踩过坑!!!
*/
public void showWelcome(){
logo.removeSelf(); // 删除logo
CCSprite welcome = CCSprite.sprite("image/welcome.jpg"); // 初始化欢迎界面
welcome.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(welcome);
}
}
除此之外,还需要导入相关的资源文件(image文件夹),将整个文件夹放入assets目录中,资源文件的获取地址如下:
http://pan.baidu.com/s/1kVScGXT 密码:zwet
package com.example.zombievsplantdemo.layer;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.instant.CCHide;
import org.cocos2d.actions.instant.CCShow;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.nodes.CCAnimation;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import java.util.ArrayList;
/**
* 欢迎页面图层
*/
public class WelcomeLayer extends BaseLayer {
/**
* logo对象
*/
private CCSprite logo;
public WelcomeLayer() {
initLogo();// 初始化logo
showLogo(); // 展示logo
}
/**
* 1.logo初始化
*/
private void initLogo(){
logo = CCSprite.sprite("image/popcap_logo.png");
logo.setPosition(size.width / 2 , size.height / 2); // 屏幕居中
this.addChild(logo);
}
/**
* 2.展示logo
*/
private void showLogo(){
CCHide hide = CCHide.action(); // 表示隐藏动作
CCDelayTime delay = CCDelayTime.action(1); // 延时一秒钟
CCShow show = CCShow.action(); // 表示显示动作
CCSequence sequence = CCSequence.actions(hide,delay,show,delay,hide,delay,CCCallFunc.action(this,"showWelcome")); // 一上来先隐藏logo,过一秒后显示logo,再过一秒钟后继续隐藏logo
logo.runAction(sequence);
}
/**
* 3.显示欢迎界面。切记因为用反射调用的该方法,所以访问修饰符一定要是public,这里踩过坑!!!
*/
public void showWelcome(){
logo.removeSelf(); // 删除logo
// 初始化欢迎页面
CCSprite welcome = CCSprite.sprite("image/welcome.jpg"); // 初始化欢迎界面
welcome.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(welcome);
// 初始化加载中的页面
CCSprite load = CCSprite.sprite("image/loading/loading_01.png"); // 初始化欢迎界面
load.setPosition(size.width / 2 , 30);
this.addChild(load);
// 获取加载动画
CCAction animate = showLoading();
load.runAction(animate);
}
/**
* 4.进度条读取页面
*/
private CCAction showLoading(){
ArrayList<CCSpriteFrame> frames = new ArrayList<>();
String format = "image/loading/loading_%02d.png"; // %02d表示两位数字,如果是个位,用0去补位(01,02);如果是十位,则不用补位(10,11)
// 初始化7帧图片
for (int i = 1; i <= 9 ; i++) {
frames.add(CCSprite.sprite(String.format(format,i)).displayedFrame());
}
CCAnimation animation = CCAnimation.animation("loading",.2f,frames); // 第二个参数表示每一帧显示时间
CCAnimate animate = CCAnimate.action(animation,false); // 第二个参数为false表示只执行一次,默认是true
return animate;
}
}
package com.example.zombievsplantdemo.util;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.nodes.CCAnimation;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import java.util.ArrayList;
/**
* 工具基类
*/
public class CommonUtil {
/**
* 动画加载方法
* @param format 文件名
* @param num 动画帧数
* @param repeat 是否循环播放
* @return 返回一个CCAction对象
*/
public static CCAction animate(String format,int num,boolean repeat){
ArrayList<CCSpriteFrame> frames = new ArrayList<>();
for (int i = 1; i <= num ; i++) {
frames.add(CCSprite.sprite(String.format(format,i)).displayedFrame());
}
CCAnimation animation = CCAnimation.animation("loading",.2f,frames); // 第二个参数表示每一帧显示时间
if (!repeat){
CCAnimate animate = CCAnimate.action(animation,false); // 第二个参数为false表示只执行一次,默认是true
return animate;
}
else {
CCAnimate animate = CCAnimate.action(animation); // 第二个参数为false表示只执行一次,默认是true
CCRepeatForever r = CCRepeatForever.action(animate);
return r;
}
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.instant.CCHide;
import org.cocos2d.actions.instant.CCShow;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.nodes.CCSprite;
/**
* 欢迎页面图层
*/
public class WelcomeLayer extends BaseLayer {
/**
* logo对象
*/
private CCSprite logo;
public WelcomeLayer() {
initLogo();// 初始化logo
showLogo(); // 展示logo
}
/**
* 1.logo初始化
*/
private void initLogo(){
logo = CCSprite.sprite("image/popcap_logo.png");
logo.setPosition(size.width / 2 , size.height / 2); // 屏幕居中
this.addChild(logo);
}
/**
* 2.展示logo
*/
private void showLogo(){
CCHide hide = CCHide.action(); // 表示隐藏动作
CCDelayTime delay = CCDelayTime.action(1); // 延时一秒钟
CCShow show = CCShow.action(); // 表示显示动作
CCSequence sequence = CCSequence.actions(hide,delay,show,delay,hide,delay,CCCallFunc.action(this,"showWelcome")); // 一上来先隐藏logo,过一秒后显示logo,再过一秒钟后继续隐藏logo
logo.runAction(sequence);
}
/**
* 3.显示欢迎界面。切记因为用反射调用的该方法,所以访问修饰符一定要是public,这里踩过坑!!!
*/
public void showWelcome(){
logo.removeSelf(); // 删除logo
// 初始化欢迎页面
CCSprite welcome = CCSprite.sprite("image/welcome.jpg"); // 初始化欢迎界面
welcome.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(welcome);
// 初始化加载中的页面
CCSprite load = CCSprite.sprite("image/loading/loading_01.png"); // 初始化欢迎界面
load.setPosition(size.width / 2 , 30);
this.addChild(load);
// 获取加载动画,使用工具类封装
CCAction animate = CommonUtil.animate("image/loading/loading_%02d.png", 9, false);
load.runAction(animate);
}
}
package com.example.zombievsplantdemo.layer;
import android.os.AsyncTask;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.instant.CCHide;
import org.cocos2d.actions.instant.CCShow;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.nodes.CCSprite;
/**
* 欢迎页面图层
*/
public class WelcomeLayer extends BaseLayer {
/**
* logo对象
*/
private CCSprite logo;
/**
* “开始游戏”按钮对象
*/
private CCSprite start;
public WelcomeLayer() {
initLogo();// 初始化logo
showLogo(); // 展示logo
}
/**
* 1.logo初始化
*/
private void initLogo(){
logo = CCSprite.sprite("image/popcap_logo.png");
logo.setPosition(size.width / 2 , size.height / 2); // 屏幕居中
this.addChild(logo);
}
/**
* 2.展示logo
*/
private void showLogo(){
CCHide hide = CCHide.action(); // 表示隐藏动作
CCDelayTime delay = CCDelayTime.action(1); // 延时一秒钟
CCShow show = CCShow.action(); // 表示显示动作
CCSequence sequence = CCSequence.actions(hide,delay,show,delay,hide,delay,CCCallFunc.action(this,"showWelcome")); // 一上来先隐藏logo,过一秒后显示logo,再过一秒钟后继续隐藏logo
logo.runAction(sequence);
// 异步在后台初始化数据
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... voids) {
try {
// 模拟耗时操作
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
start.setVisible(true); // 显示点击开始按钮
}
}.execute();
}
/**
* 3.显示欢迎界面。切记因为用反射调用的该方法,所以访问修饰符一定要是public,这里踩过坑!!!
*/
public void showWelcome(){
logo.removeSelf(); // 删除logo
// 初始化欢迎页面
CCSprite welcome = CCSprite.sprite("image/welcome.jpg"); // 初始化欢迎界面
welcome.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(welcome);
// 初始化加载中的页面
CCSprite load = CCSprite.sprite("image/loading/loading_01.png"); // 初始化欢迎界面
load.setPosition(size.width / 2 , 30);
this.addChild(load);
// 初始化加载完后的动画(点击开始)
start = CCSprite.sprite("image/loading/loading_start.png"); // 初始化欢迎界面
start.setPosition(size.width / 2 , 30);
start.setVisible(false); // 隐藏按钮
this.addChild(start);
// 获取加载动画,使用工具类封装
CCAction animate = CommonUtil.animate("image/loading/loading_%02d.png", 9, false);
load.runAction(animate);
}
}
在Layer包下新建游戏主菜单与层MenuLayer,添加showMainMenu()方法,代码如下:
package com.example.zombievsplantdemo.layer;
import org.cocos2d.nodes.CCSprite;
/**
* 菜单图层
*/
public class MenuLayer extends BaseLayer{
public MenuLayer() {
showMainMenu();
}
/**
* 1.初始化主菜单页面
*/
private void showMainMenu(){
CCSprite background = CCSprite.sprite("image/menu/main_menu_bg.jpg");
background.setAnchorPoint(0,0);
this.addChild(background);
}
}
修改WelcomeLayer,为“游戏开始”按钮注册点击事件,添加切换图层方法changeLayer()。注意:这里要在“游戏按钮”出现时允许图层可以触摸,代码如下:
package com.example.zombievsplantdemo.layer;
import android.os.AsyncTask;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.instant.CCHide;
import org.cocos2d.actions.instant.CCShow;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
/**
* 欢迎页面图层
*/
public class WelcomeLayer extends BaseLayer {
/**
* logo对象
*/
private CCSprite logo;
/**
* “开始游戏”按钮对象
*/
private CCSprite start;
public WelcomeLayer() {
initLogo();// 初始化logo
showLogo(); // 展示logo
}
/**
* 1.logo初始化
*/
private void initLogo(){
logo = CCSprite.sprite("image/popcap_logo.png");
logo.setPosition(size.width / 2 , size.height / 2); // 屏幕居中
this.addChild(logo);
}
/**
* 2.展示logo
*/
private void showLogo(){
CCHide hide = CCHide.action(); // 表示隐藏动作
CCDelayTime delay = CCDelayTime.action(1); // 延时一秒钟
CCShow show = CCShow.action(); // 表示显示动作
CCSequence sequence = CCSequence.actions(hide,delay,show,delay,hide,delay,CCCallFunc.action(this,"showWelcome")); // 一上来先隐藏logo,过一秒后显示logo,再过一秒钟后继续隐藏logo
logo.runAction(sequence);
// 异步在后台初始化数据
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... voids) {
try {
// 模拟耗时操作
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
start.setVisible(true); // 显示点击开始按钮
setIsTouchEnabled(true); // 开启触摸事件
}
}.execute();
}
/**
* 3.显示欢迎界面。切记因为用反射调用的该方法,所以访问修饰符一定要是public,这里踩过坑!!!
*/
public void showWelcome(){
logo.removeSelf(); // 删除logo
// 初始化欢迎页面
CCSprite welcome = CCSprite.sprite("image/welcome.jpg"); // 初始化欢迎界面
welcome.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(welcome);
// 初始化加载中的页面
CCSprite load = CCSprite.sprite("image/loading/loading_01.png"); // 初始化欢迎界面
load.setPosition(size.width / 2 , 30);
this.addChild(load);
// 初始化加载完后的动画(点击开始)
start = CCSprite.sprite("image/loading/loading_start.png"); // 初始化欢迎界面
start.setPosition(size.width / 2 , 30);
start.setVisible(false); // 隐藏按钮
this.addChild(start);
// 获取加载动画,使用工具类封装的方法
CCAction animate = CommonUtil.animate("image/loading/loading_%02d.png", 9, false);
load.runAction(animate);
}
/**
* 4.切换图层
*/
private void changeLayer(){
CCScene scene = CCScene.node();
scene.addChild(new MenuLayer());
CCJumpZoomTransition transition = CCJumpZoomTransition.transition(2, scene); // 添加转场效果
CCDirector.sharedDirector().replaceScene(transitions); // 表示导演要切换场景
}
/**
* 5.为“开始游戏”按钮注册点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
if (CGRect.containsPoint(start.getBoundingBox(),point)){
changeLayer();
}
return super.ccTouchesBegan(event);
}
}
package com.example.zombievsplantdemo.util;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCAnimation;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import org.cocos2d.transitions.CCFadeTransition;
import java.util.ArrayList;
/**
* 工具类
*/
public class CommonUtil {
/**
* 动画加载方法
* @param format 文件名
* @param num 动画帧数
* @param repeat 是否循环播放
* @return 返回一个CCAction对象
*/
public static CCAction animate(String format,int num,boolean repeat){
ArrayList<CCSpriteFrame> frames = new ArrayList<>();
for (int i = 1; i <= num ; i++) {
frames.add(CCSprite.sprite(String.format(format,i)).displayedFrame());
}
CCAnimation animation = CCAnimation.animation("loading",.2f,frames); // 第二个参数表示每一帧显示时间
if (!repeat){
CCAnimate animate = CCAnimate.action(animation,false); // 第二个参数为false表示只执行一次,默认是true
return animate;
}
else {
CCAnimate animate = CCAnimate.action(animation); // 第二个参数为false表示只执行一次,默认是true
CCRepeatForever r = CCRepeatForever.action(animate);
return r;
}
}
/**
* 用淡入淡出效果实现转场
* @param layer
*/
public static void changeLayer(CCLayer layer){
CCScene scene = CCScene.node();
scene.addChild(layer);
CCFadeTransition transition = CCFadeTransition.transition(1,scene); // 淡入淡出效果
CCDirector.sharedDirector().replaceScene(transition); // 表示导演要切换场景
}
}
package com.example.zombievsplantdemo.layer;
import android.os.AsyncTask;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.instant.CCHide;
import org.cocos2d.actions.instant.CCShow;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
/**
* 欢迎页面图层
*/
public class WelcomeLayer extends BaseLayer {
/**
* logo对象
*/
private CCSprite logo;
/**
* “开始游戏”按钮对象
*/
private CCSprite start;
public WelcomeLayer() {
initLogo();// 初始化logo
showLogo(); // 展示logo
}
/**
* 1.logo初始化
*/
private void initLogo(){
logo = CCSprite.sprite("image/popcap_logo.png");
logo.setPosition(size.width / 2 , size.height / 2); // 屏幕居中
this.addChild(logo);
}
/**
* 2.展示logo
*/
private void showLogo(){
CCHide hide = CCHide.action(); // 表示隐藏动作
CCDelayTime delay = CCDelayTime.action(1); // 延时一秒钟
CCShow show = CCShow.action(); // 表示显示动作
CCSequence sequence = CCSequence.actions(hide,delay,show,delay,hide,delay,CCCallFunc.action(this,"showWelcome")); // 一上来先隐藏logo,过一秒后显示logo,再过一秒钟后继续隐藏logo
logo.runAction(sequence);
// 异步在后台初始化数据
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... voids) {
try {
// 模拟耗时操作
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
start.setVisible(true); // 显示点击开始按钮
setIsTouchEnabled(true); // 开启触摸事件
}
}.execute();
}
/**
* 3.显示欢迎界面。切记因为用反射调用的该方法,所以访问修饰符一定要是public,这里踩过坑!!!
*/
public void showWelcome(){
logo.removeSelf(); // 删除logo
// 初始化欢迎页面
CCSprite welcome = CCSprite.sprite("image/welcome.jpg"); // 初始化欢迎界面
welcome.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(welcome);
// 初始化加载中的页面
CCSprite load = CCSprite.sprite("image/loading/loading_01.png"); // 初始化欢迎界面
load.setPosition(size.width / 2 , 30);
this.addChild(load);
// 初始化加载完后的动画(点击开始)
start = CCSprite.sprite("image/loading/loading_start.png"); // 初始化欢迎界面
start.setPosition(size.width / 2 , 30);
start.setVisible(false); // 隐藏按钮
this.addChild(start);
// 获取加载动画,使用工具类封装的方法
CCAction animate = CommonUtil.animate("image/loading/loading_%02d.png", 9, false);
load.runAction(animate);
}
/**
* 4.为“开始游戏”按钮注册点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
if (CGRect.containsPoint(start.getBoundingBox(),point)){
CommonUtil.changeLayer(new MenuLayer());
}
return super.ccTouchesBegan(event);
}
}
package com.example.zombievsplantdemo.layer;
import org.cocos2d.menus.CCMenu;
import org.cocos2d.menus.CCMenuItemSprite;
import org.cocos2d.nodes.CCSprite;
/**
* 菜单图层
*/
public class MenuLayer extends BaseLayer{
public MenuLayer() {
showMainMenu();
showStart();
}
/**
* 1.初始化主菜单页面
*/
private void showMainMenu(){
CCSprite background = CCSprite.sprite("image/menu/main_menu_bg.jpg");
background.setAnchorPoint(0,0);
this.addChild(background);
}
/**
* 2.主菜单的逻辑
*/
private void showStart(){
// 默认的按钮
CCSprite normalStart = CCSprite.sprite("image/menu/start_adventure_default.png");
// 被选中的按钮
CCSprite selectStart = CCSprite.sprite("image/menu/start_adventure_press.png");
CCMenu menu = CCMenu.menu();
CCMenuItemSprite items = CCMenuItemSprite.item(normalStart,selectStart,this,"clickStart");
menu.addChild(items);
menu.setScale(0.5f);
menu.setPosition(size.width / 2 - 25,size.height / 2 - 110);
menu.setRotation(4.5f);
this.addChild(menu);
}
/**
* 3.“开始冒险吧”的点击事件
* @param obj 必须携带的参数,不然无法被反射到
*/
public void clickStart(Object obj){
System.out.println("点击!");
}
}
package com.example.zombievsplantdemo.layer;
import org.cocos2d.layers.CCTMXTiledMap;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
public FightLayer() {
loadMap();
}
/**
* 1.加载地图
*/
private void loadMap(){
CCTMXTiledMap map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.menus.CCMenu;
import org.cocos2d.menus.CCMenuItemSprite;
import org.cocos2d.nodes.CCSprite;
/**
* 菜单图层
*/
public class MenuLayer extends BaseLayer{
public MenuLayer() {
showMainMenu();
showStart();
}
/**
* 1.初始化主菜单页面
*/
private void showMainMenu(){
CCSprite background = CCSprite.sprite("image/menu/main_menu_bg.jpg");
background.setAnchorPoint(0,0);
this.addChild(background);
}
/**
* 2.主菜单的逻辑
*/
private void showStart(){
// 默认的按钮
CCSprite normalStart = CCSprite.sprite("image/menu/start_adventure_default.png");
// 被选中的按钮
CCSprite selectStart = CCSprite.sprite("image/menu/start_adventure_press.png");
CCMenu menu = CCMenu.menu();
CCMenuItemSprite items = CCMenuItemSprite.item(normalStart,selectStart,this,"clickStart");
menu.addChild(items);
menu.setScale(0.5f);
menu.setPosition(size.width / 2 - 25,size.height / 2 - 110);
menu.setRotation(4.5f);
this.addChild(menu);
}
/**
* 3.“开始冒险吧”的点击事件
* @param obj 必须携带的参数,不然无法被反射到
*/
public void clickStart(Object obj){
CommonUtil.changeLayer(new FightLayer());
}
}
package com.example.zombievsplantdemo.layer;
import org.cocos2d.layers.CCTMXObjectGroup;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
import java.util.HashMap;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
public FightLayer() {
loadMap();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
loadZombiePoint();
}
/**
* 2.加载僵尸的坐标点集合
* @return
*/
private ArrayList<CGPoint> loadZombiePoint(){
ArrayList<CGPoint> tempPoints = new ArrayList<>();
CCTMXObjectGroup zombies = map.objectGroupNamed("zombies");
ArrayList<HashMap<String, String>> zombiesPoint = zombies.objects;
for (HashMap<String, String> map : zombiesPoint) {
Integer x = Integer.parseInt(map.get("x"));
Integer y = Integer.parseInt(map.get("y"));
tempPoints.add(ccp(x,y));
}
return tempPoints;
}
}
package com.example.zombievsplantdemo.util;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.layers.CCTMXObjectGroup;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCAnimation;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCNode;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import org.cocos2d.transitions.CCFadeTransition;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
import java.util.HashMap;
import static org.cocos2d.types.CGPoint.ccp;
/**
* 工具类
*/
public class CommonUtil {
/**
* 动画加载方法
* @param format 文件名
* @param num 动画帧数
* @param repeat 是否循环播放
* @return 返回一个CCAction对象
*/
public static CCAction animate(String format,int num,boolean repeat){
ArrayList<CCSpriteFrame> frames = new ArrayList<>();
for (int i = 1; i <= num ; i++) {
frames.add(CCSprite.sprite(String.format(format,i)).displayedFrame());
}
CCAnimation animation = CCAnimation.animation("loading",.2f,frames); // 第二个参数表示每一帧显示时间
if (!repeat){
CCAnimate animate = CCAnimate.action(animation,false); // 第二个参数为false表示只执行一次,默认是true
return animate;
}
else {
CCAnimate animate = CCAnimate.action(animation); // 第二个参数为false表示只执行一次,默认是true
CCRepeatForever r = CCRepeatForever.action(animate);
return r;
}
}
/**
* 用淡入淡出效果实现转场
* @param layer
*/
public static void changeLayer(CCLayer layer){
CCScene scene = CCScene.node();
scene.addChild(layer);
CCFadeTransition transition = CCFadeTransition.transition(1,scene); // 淡入淡出效果
CCDirector.sharedDirector().replaceScene(transition); // 表示导演要切换场景
}
/**
* 加载坐标蒂娜
* @param map 地图
* @param groupName 组名
* @return
*/
public static ArrayList<CGPoint> loadPoint(CCTMXTiledMap map,String groupName){
ArrayList<CGPoint> tempPoints = new ArrayList<>();
CCTMXObjectGroup tempPointGruops = map.objectGroupNamed(groupName);
ArrayList<HashMap<String, String>> zombiesPoint = tempPointGruops.objects;
for (HashMap<String, String> tempmap : zombiesPoint) {
Integer x = Integer.parseInt(tempmap.get("x"));
Integer y = Integer.parseInt(tempmap.get("y"));
tempPoints.add(CCNode.ccp(x,y));
}
return tempPoints;
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
public FightLayer() {
loadMap();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
public FightLayer() {
loadMap();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move);
map.runAction(sequence);
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.nodes.CCSprite;
/**
* 僵尸的实体类
*/
public class Zombie extends CCSprite {
public Zombie(){
super("image/zombies/zombies_1/shake/z_1_01.png"); // 初始化僵尸图片
setScale(0.5); // 设置僵尸大小
setAnchorPoint(0.5f,0); // 设置锚点为两脚之间
CCAction animate = CommonUtil.animate("image/zombies/zombies_1/shake/z_1_%02d.png", 2, true);
runAction(animate); // 让僵尸去颤抖
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move);
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
}
}
代码如下:
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
String format = "image/fight/chose/choose_default%02d.png";
for (int i = 1; i <= 9 ; i++) {
CCSprite plant = CCSprite.sprite(String.format(format,i));
float x = (i - 1) % 4 * 54 + 16; // 计算x坐标
float y = 175 - (i - 1) / 4 * 59; // 计算y坐标
plant.setAnchorPoint(0,0); // 设置锚点为左下角
plant.setPosition(x,y);
mChooseBox.addChild(plant);
}
}
}
package com.example.zombievsplantdemo.domain;
import org.cocos2d.nodes.CCSprite;
/**
* 植物的实体类
*/
public class Plant {
/**
* 植物图标
*/
private String format = "image/fight/chose/choose_default%02d.png";
/**
* 背景图片(半透明)
*/
private CCSprite bgPlant;
/**
* 背景图片(展现)
*/
private CCSprite showPlant;
public Plant(int i) {
initBgPlant(i);
initShowPlant(i);
}
/**
* 初始化植物背景图标(半透明)
* @param i 植物图标的序号
*/
private void initBgPlant(int i){
bgPlant = CCSprite.sprite(String.format(format,i));
float x = (i - 1) % 4 * 54 + 16; // 计算x坐标
float y = 175 - (i - 1) / 4 * 59; // 计算y坐标
bgPlant.setAnchorPoint(0,0); // 设置锚点为左下角
bgPlant.setPosition(x,y);
bgPlant.setOpacity(100); // 设置为半透明
}
/**
* 初始化植物背景图标(展现)
* @param i 植物图标的序号
*/
private void initShowPlant(int i){
showPlant = CCSprite.sprite(String.format(format,i));
float x = (i - 1) % 4 * 54 + 16; // 计算x坐标
float y = 175 - (i - 1) / 4 * 59; // 计算y坐标
showPlant.setAnchorPoint(0,0); // 设置锚点为左下角
showPlant.setPosition(x,y);
}
public CCSprite getBgPlant() {
return bgPlant;
}
public CCSprite getShowPlant() {
return showPlant;
}
}
package com.example.zombievsplantdemo.layer;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
}
}
}
package com.example.zombievsplantdemo.layer;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
/**
* 选择框内植物的集合
*/
private CopyOnWriteArrayList<Plant> mPlants;
/**
* 已选植物的集合
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants = new CopyOnWriteArrayList<>();
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
setIsTouchEnabled(true); // 打开点击事件
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
mPlants = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
mPlants.add(plant);
}
}
/**
* 7.为植物图标注册点击事件,注意要打开点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
// 是否落在植物选择框内
if (CGRect.containsPoint(mChooseBox.getBoundingBox(),point)){
for (Plant mPlant : mPlants) {
if (CGRect.containsPoint(mPlant.getShowPlant().getBoundingBox(),point)){
if (mSelectedPlants.size() < 5){
mSelectedPlants.add(mPlant);
CCMoveTo move = CCMoveTo.action(0.5f,ccp(75 + ( mSelectedPlants.size() - 1 ) * 53,size.height - 65)); // 植物移动到已选框内
mPlant.getShowPlant().runAction(move);
}
break;
}
}
}
else if (CGRect.containsPoint(mSelectedBox.getBoundingBox(),point)){
boolean isSelect = false;
for (Plant mSelectedPlant : mSelectedPlants) {
if (CGRect.containsPoint(mSelectedPlant.getShowPlant().getBoundingBox(),point)){
CCMoveTo move = CCMoveTo.action(0.5f,mSelectedPlant.getBgPlant().getPosition()); // 移动到背景植物的位置
mSelectedPlant.getShowPlant().runAction(move);
mSelectedPlants.remove(mSelectedPlant); // 移除取消的植物
isSelect = true;
continue;
}
if (isSelect){ // 说明有植物被点击了
CCMoveBy move = CCMoveBy.action(0.5f,ccp(-53,0)); // 向左便宜;
mSelectedPlant.getShowPlant().runAction(move);
}
}
}
return super.ccTouchesBegan(event);
}
}
package com.example.zombievsplantdemo.layer;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
/**
* 选择框内植物的集合
*/
private CopyOnWriteArrayList<Plant> mPlants;
/**
* 已选植物的集合
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants = new CopyOnWriteArrayList<>();
/**
* 标记植物是否正在被移动
*/
private boolean isMoving = false;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
setIsTouchEnabled(true); // 打开点击事件
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
mPlants = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
mPlants.add(plant);
}
}
/**
* 7.为植物图标注册点击事件,注意要打开点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
// 是否落在植物选择框内
if (CGRect.containsPoint(mChooseBox.getBoundingBox(),point)){
for (Plant mPlant : mPlants) {
if (CGRect.containsPoint(mPlant.getShowPlant().getBoundingBox(),point)){
if (mSelectedPlants.size() < 5 && !isMoving){
isMoving = true;
mSelectedPlants.add(mPlant);
CCMoveTo move = CCMoveTo.action(0.5f,ccp(75 + ( mSelectedPlants.size() - 1 ) * 53,size.height - 65)); // 植物移动到已选框内
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"unLock"));
mPlant.getShowPlant().runAction(sequence);
}
break;
}
}
}
else if (CGRect.containsPoint(mSelectedBox.getBoundingBox(),point)){
boolean isSelect = false;
for (Plant mSelectedPlant : mSelectedPlants) {
if (CGRect.containsPoint(mSelectedPlant.getShowPlant().getBoundingBox(),point)){
CCMoveTo move = CCMoveTo.action(0.5f,mSelectedPlant.getBgPlant().getPosition()); // 移动到背景植物的位置
mSelectedPlant.getShowPlant().runAction(move);
mSelectedPlants.remove(mSelectedPlant); // 移除取消的植物
isSelect = true;
continue;
}
if (isSelect){ // 说明有植物被点击了
CCMoveBy move = CCMoveBy.action(0.5f,ccp(-53,0)); // 向左偏移;
mSelectedPlant.getShowPlant().runAction(move);
}
}
}
return super.ccTouchesBegan(event);
}
/**
* 8.重置植物移动的标记位
*/
public void unLock(){
isMoving = false;
}
}
package com.example.zombievsplantdemo.layer;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
/**
* 选择框内植物的集合
*/
private CopyOnWriteArrayList<Plant> mPlants;
/**
* 已选植物的集合
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants = new CopyOnWriteArrayList<>();
/**
* 标记植物是否正在被移动
*/
private boolean isMoving = false;
/**
* 开始战斗的按钮
*/
private CCSprite start;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
setIsTouchEnabled(true); // 打开点击事件
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
mPlants = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
mPlants.add(plant);
}
// 添加开始战斗的按钮
start = CCSprite.sprite("image/fight/chose/fight_start.png");
start.setPosition(mChooseBox.getContentSize().width / 2 , 30);
mChooseBox.addChild(start);
}
/**
* 7.为植物图标注册点击事件,注意要打开点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
// 是否落在植物选择框内
if (CGRect.containsPoint(mChooseBox.getBoundingBox(),point)){
if (CGRect.containsPoint(start.getBoundingBox(),point)){ // 开始战斗被点击
gamePrepare();
return true;
}
for (Plant mPlant : mPlants) {
if (CGRect.containsPoint(mPlant.getShowPlant().getBoundingBox(),point)){
if (mSelectedPlants.size() < 5 && !isMoving){
isMoving = true;
mSelectedPlants.add(mPlant);
CCMoveTo move = CCMoveTo.action(0.5f,ccp(75 + ( mSelectedPlants.size() - 1 ) * 53,size.height - 65)); // 植物移动到已选框内
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"unLock"));
mPlant.getShowPlant().runAction(sequence);
}
break;
}
}
}
else if (CGRect.containsPoint(mSelectedBox.getBoundingBox(),point)){
boolean isSelect = false;
for (Plant mSelectedPlant : mSelectedPlants) {
if (CGRect.containsPoint(mSelectedPlant.getShowPlant().getBoundingBox(),point)){
CCMoveTo move = CCMoveTo.action(0.5f,mSelectedPlant.getBgPlant().getPosition()); // 移动到背景植物的位置
mSelectedPlant.getShowPlant().runAction(move);
mSelectedPlants.remove(mSelectedPlant); // 移除取消的植物
isSelect = true;
continue;
}
if (isSelect){ // 说明有植物被点击了
CCMoveBy move = CCMoveBy.action(0.5f,ccp(-53,0)); // 向左偏移;
mSelectedPlant.getShowPlant().runAction(move);
}
}
}
return super.ccTouchesBegan(event);
}
/**
* 8.重置植物移动的标记位
*/
public void unLock(){
isMoving = false;
}
/**
* 9.点击“开始战斗”后,游戏资源的准备
*/
private void gamePrepare(){
System.out.println("开始战斗");
}
}
package com.example.zombievsplantdemo.layer;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
/**
* 选择框内植物的集合
*/
private CopyOnWriteArrayList<Plant> mPlants;
/**
* 已选植物的集合
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants = new CopyOnWriteArrayList<>();
/**
* 标记植物是否正在被移动
*/
private boolean isMoving = false;
/**
* 开始战斗的按钮
*/
private CCSprite start;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
setIsTouchEnabled(true); // 打开点击事件
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
mPlants = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
mPlants.add(plant);
}
// 添加开始战斗的按钮
start = CCSprite.sprite("image/fight/chose/fight_start.png");
start.setPosition(mChooseBox.getContentSize().width / 2 , 30);
mChooseBox.addChild(start);
}
/**
* 7.为植物图标注册点击事件,注意要打开点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
// 是否落在植物选择框内
if (CGRect.containsPoint(mChooseBox.getBoundingBox(),point)){
if (CGRect.containsPoint(start.getBoundingBox(),point)){ // 开始战斗被点击
gamePrepare();
return true;
}
for (Plant mPlant : mPlants) {
if (CGRect.containsPoint(mPlant.getShowPlant().getBoundingBox(),point)){
if (mSelectedPlants.size() < 5 && !isMoving){
isMoving = true;
mSelectedPlants.add(mPlant);
CCMoveTo move = CCMoveTo.action(0.5f,ccp(75 + ( mSelectedPlants.size() - 1 ) * 53,size.height - 65)); // 植物移动到已选框内
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"unLock"));
mPlant.getShowPlant().runAction(sequence);
}
break;
}
}
}
else if (CGRect.containsPoint(mSelectedBox.getBoundingBox(),point)){
boolean isSelect = false;
for (Plant mSelectedPlant : mSelectedPlants) {
if (CGRect.containsPoint(mSelectedPlant.getShowPlant().getBoundingBox(),point)){
CCMoveTo move = CCMoveTo.action(0.5f,mSelectedPlant.getBgPlant().getPosition()); // 移动到背景植物的位置
mSelectedPlant.getShowPlant().runAction(move);
mSelectedPlants.remove(mSelectedPlant); // 移除取消的植物
isSelect = true;
continue;
}
if (isSelect){ // 说明有植物被点击了
CCMoveBy move = CCMoveBy.action(0.5f,ccp(-53,0)); // 向左偏移;
mSelectedPlant.getShowPlant().runAction(move);
}
}
}
return super.ccTouchesBegan(event);
}
/**
* 8.重置植物移动的标记位
*/
public void unLock(){
isMoving = false;
}
/**
* 9.点击“开始战斗”后,游戏资源的准备
*/
private void gamePrepare(){
//隐藏植物框
mChooseBox.removeSelf();
//地图移动回去
moveMapBack();
//缩放已选框
mSelectedBox.setScale(0.65);
//回收僵尸
}
/**
* 10.地图反向移动
*/
private void moveMapBack(){
float offset = map.getContentSize().width - size.width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move);
map.runAction(sequence);
}
}
package com.example.zombievsplantdemo.util;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.layers.CCTMXObjectGroup;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCAnimation;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCNode;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import org.cocos2d.transitions.CCFadeTransition;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
import java.util.HashMap;
/**
* 工具类
*/
public class CommonUtil {
/**
* 动画加载方法(1)
* @param format 文件名
* @param num 动画帧数
* @param repeat 是否循环播放
* @param t 动画播放时间
* @return 返回一个CCAction对象
*/
public static CCAction animate(String format,int num,boolean repeat,float t){
ArrayList<CCSpriteFrame> frames = new ArrayList<>();
for (int i = 1; i <= num ; i++) {
frames.add(CCSprite.sprite(String.format(format,i)).displayedFrame());
}
CCAnimation animation = CCAnimation.animation("loading",t,frames); // 第二个参数表示每一帧显示时间
if (!repeat){
CCAnimate animate = CCAnimate.action(animation,false); // 第二个参数为false表示只执行一次,默认是true
return animate;
}
else {
CCAnimate animate = CCAnimate.action(animation); // 第二个参数为false表示只执行一次,默认是true
CCRepeatForever r = CCRepeatForever.action(animate);
return r;
}
}
/**
* 动画加载方法(2)
* @param format 文件名
* @param num 动画帧数
* @param repeat 是否循环播放
* @return 返回一个CCAction对象
*/
public static CCAction animate(String format,int num,boolean repeat){
return animate(format,num,repeat,0.2f);
}
/**
* 用淡入淡出效果实现转场
* @param layer
*/
public static void changeLayer(CCLayer layer){
CCScene scene = CCScene.node();
scene.addChild(layer);
CCFadeTransition transition = CCFadeTransition.transition(1,scene); // 淡入淡出效果
CCDirector.sharedDirector().replaceScene(transition); // 表示导演要切换场景
}
/**
* 加载坐标蒂娜
* @param map 地图
* @param groupName 组名
* @return
*/
public static ArrayList<CGPoint> loadPoint(CCTMXTiledMap map,String groupName){
ArrayList<CGPoint> tempPoints = new ArrayList<>();
CCTMXObjectGroup tempPointGruops = map.objectGroupNamed(groupName);
ArrayList<HashMap<String, String>> zombiesPoint = tempPointGruops.objects;
for (HashMap<String, String> tempmap : zombiesPoint) {
Integer x = Integer.parseInt(tempmap.get("x"));
Integer y = Integer.parseInt(tempmap.get("y"));
tempPoints.add(CCNode.ccp(x,y));
}
return tempPoints;
}
}
package com.example.zombievsplantdemo.layer;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
/**
* 选择框内植物的集合
*/
private CopyOnWriteArrayList<Plant> mPlants;
/**
* 已选植物的集合
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants = new CopyOnWriteArrayList<>();
/**
* 标记植物是否正在被移动
*/
private boolean isMoving = false;
/**
* 开始战斗的按钮
*/
private CCSprite start;
/**
* 展示僵尸的集合
*/
private ArrayList<Zombie> mShowZombies;
/**
* 展示“准备——安放——植物”的文本框
*/
private CCSprite startLabel;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
mShowZombies = new ArrayList<>();
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
mShowZombies.add(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
setIsTouchEnabled(true); // 打开点击事件
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
mPlants = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
mPlants.add(plant);
}
// 添加开始战斗的按钮
start = CCSprite.sprite("image/fight/chose/fight_start.png");
start.setPosition(mChooseBox.getContentSize().width / 2 , 30);
mChooseBox.addChild(start);
}
/**
* 7.为植物图标注册点击事件,注意要打开点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint point = convertTouchToNodeSpace(event);
// 是否落在植物选择框内
if (CGRect.containsPoint(mChooseBox.getBoundingBox(),point)){
if (CGRect.containsPoint(start.getBoundingBox(),point)){ // 开始战斗被点击
if (!mSelectedPlants.isEmpty()){
gamePrepare();
}
return true;
}
for (Plant mPlant : mPlants) {
if (CGRect.containsPoint(mPlant.getShowPlant().getBoundingBox(),point)){
if (mSelectedPlants.size() < 5 && !isMoving){
isMoving = true;
mSelectedPlants.add(mPlant);
CCMoveTo move = CCMoveTo.action(0.5f,ccp(75 + ( mSelectedPlants.size() - 1 ) * 53,size.height - 65)); // 植物移动到已选框内
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"unLock"));
mPlant.getShowPlant().runAction(sequence);
}
break;
}
}
}
else if (CGRect.containsPoint(mSelectedBox.getBoundingBox(),point)){
boolean isSelect = false;
for (Plant mSelectedPlant : mSelectedPlants) {
if (CGRect.containsPoint(mSelectedPlant.getShowPlant().getBoundingBox(),point)){
CCMoveTo move = CCMoveTo.action(0.5f,mSelectedPlant.getBgPlant().getPosition()); // 移动到背景植物的位置
mSelectedPlant.getShowPlant().runAction(move);
mSelectedPlants.remove(mSelectedPlant); // 移除取消的植物
isSelect = true;
continue;
}
if (isSelect){ // 说明有植物被点击了
CCMoveBy move = CCMoveBy.action(0.5f,ccp(-53,0)); // 向左偏移;
mSelectedPlant.getShowPlant().runAction(move);
}
}
}
return super.ccTouchesBegan(event);
}
/**
* 8.重置植物移动的标记位
*/
public void unLock(){
isMoving = false;
}
/**
* 9.点击“开始战斗”后,游戏资源的准备
*/
private void gamePrepare(){
//隐藏植物框
mChooseBox.removeSelf();
//地图移动回去
moveMapBack();
//缩放已选框
mSelectedBox.setScale(0.65);
for (Plant plant : mSelectedPlants) {
plant.getShowPlant().setScale(0.65f); // 跟父容器同步缩小
plant.getShowPlant().setPosition(plant.getShowPlant().getPosition().x * 0.65f,
plant.getShowPlant().getPosition().y + (size.height - plant.getShowPlant().getPosition().y) * 0.35f);
this.addChild(plant.getShowPlant());
}
}
/**
* 10.地图反向移动
*/
private void moveMapBack(){
float offset = map.getContentSize().width - size.width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showLabel"));
map.runAction(sequence);
}
/**
* 11.游戏开始前的文字展示
*/
public void showLabel(){
//回收僵尸,节省内存
for (Zombie zombie : mShowZombies) {
zombie.removeSelf();
}
mShowZombies.clear();
//显示准备开始战斗的文字
startLabel = CCSprite.sprite("image/fight/startready_01.png");
startLabel.setPosition(size.width / 2 , size.height / 2);
this.addChild(startLabel);
CCAnimate animate = (CCAnimate) CommonUtil.animate("image/fight/startready_%02d.png", 3, false,0.5f);
CCSequence sequence = CCSequence.actions(animate,CCCallFunc.action(this,"gameStart"));
startLabel.runAction(sequence);
}
/**
* 12.游戏正式开始的处理
*/
public void gameStart(){
startLabel.removeSelf();
System.out.println("游戏正式开始");
}
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import org.cocos2d.layers.CCTMXTiledMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
}
}
package com.example.zombievsplantdemo.layer;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.Zombie;
import com.example.zombievsplantdemo.engine.GameEngine;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 战斗图层
*/
public class FightLayer extends BaseLayer{
/**
* 地图对象
*/
private CCTMXTiledMap map;
/**
* 僵尸的坐标点集合
*/
private ArrayList<CGPoint> mZombiesPoints;
/**
* 已选植物框
*/
private CCSprite mSelectedBox;
/**
* 未选植物框
*/
private CCSprite mChooseBox;
/**
* 选择框内植物的集合
*/
private CopyOnWriteArrayList<Plant> mPlants;
/**
* 已选植物的集合
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants = new CopyOnWriteArrayList<>();
/**
* 标记植物是否正在被移动
*/
private boolean isMoving = false;
/**
* 开始战斗的按钮
*/
private CCSprite start;
/**
* 展示僵尸的集合
*/
private ArrayList<Zombie> mShowZombies;
/**
* 展示“准备——安放——植物”的文本框
*/
private CCSprite startLabel;
public FightLayer() {
loadMap();
loadZombie();
}
/**
* 1.加载地图
*/
private void loadMap(){
map = CCTMXTiledMap.tiledMap("image/fight/map_day.tmx");
this.addChild(map);
mZombiesPoints = CommonUtil.loadPoint(map, "zombies");
moveMap();
}
/**
* 2.移动地图
*/
private void moveMap(){
float offset = size.width - map.getContentSize().width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showPlantBox"));
map.runAction(sequence);
}
/**
* 3.加载僵尸
*/
private void loadZombie(){
mShowZombies = new ArrayList<>();
for (CGPoint mZombiesPoint : mZombiesPoints) {
Zombie zombie = new Zombie();
zombie.setPosition(mZombiesPoint);
map.addChild(zombie);
mShowZombies.add(zombie);
}
}
/**
* 4.展示植物框
*/
public void showPlantBox(){
setIsTouchEnabled(true); // 打开点击事件
showSelectedBox();
showChooseBox();
}
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox);
}
/**
* 6.展示植物选择框(未选)
*/
private void showChooseBox(){
mChooseBox = CCSprite.sprite("image/fight/chose/fight_choose.png");
mChooseBox.setAnchorPoint(0,0); // 设置锚点为左下角
this.addChild(mChooseBox);
mPlants = new CopyOnWriteArrayList<>();
for (int i = 1; i <= 9 ; i++) {
Plant plant = new Plant(i);
// 添加背景植物和展示植物,位置一样
mChooseBox.addChild(plant.getBgPlant());
mChooseBox.addChild(plant.getShowPlant());
mPlants.add(plant);
}
// 添加开始战斗的按钮
start = CCSprite.sprite("image/fight/chose/fight_start.png");
start.setPosition(mChooseBox.getContentSize().width / 2 , 30);
mChooseBox.addChild(start);
}
/**
* 7.为植物图标注册点击事件,注意要打开点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
// 判断游戏是否已经开始
if(GameEngine.isStart){
GameEngine.getInstance().handleTouch(event);
return true;
}
CGPoint point = convertTouchToNodeSpace(event);
// 是否落在植物选择框内
if (CGRect.containsPoint(mChooseBox.getBoundingBox(),point)){
if (CGRect.containsPoint(start.getBoundingBox(),point)){ // 开始战斗被点击
if (!mSelectedPlants.isEmpty()){
gamePrepare();
}
return true;
}
for (Plant mPlant : mPlants) {
if (CGRect.containsPoint(mPlant.getShowPlant().getBoundingBox(),point)){
if (mSelectedPlants.size() < 5 && !isMoving){
isMoving = true;
mSelectedPlants.add(mPlant);
CCMoveTo move = CCMoveTo.action(0.5f,ccp(75 + ( mSelectedPlants.size() - 1 ) * 53,size.height - 65)); // 植物移动到已选框内
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"unLock"));
mPlant.getShowPlant().runAction(sequence);
}
break;
}
}
}
else if (CGRect.containsPoint(mSelectedBox.getBoundingBox(),point)){
boolean isSelect = false;
for (Plant mSelectedPlant : mSelectedPlants) {
if (CGRect.containsPoint(mSelectedPlant.getShowPlant().getBoundingBox(),point)){
CCMoveTo move = CCMoveTo.action(0.5f,mSelectedPlant.getBgPlant().getPosition()); // 移动到背景植物的位置
mSelectedPlant.getShowPlant().runAction(move);
mSelectedPlants.remove(mSelectedPlant); // 移除取消的植物
isSelect = true;
continue;
}
if (isSelect){ // 说明有植物被点击了
CCMoveBy move = CCMoveBy.action(0.5f,ccp(-53,0)); // 向左偏移;
mSelectedPlant.getShowPlant().runAction(move);
}
}
}
return super.ccTouchesBegan(event);
}
/**
* 8.重置植物移动的标记位
*/
public void unLock(){
isMoving = false;
}
/**
* 9.点击“开始战斗”后,游戏资源的准备
*/
private void gamePrepare(){
//隐藏植物框
mChooseBox.removeSelf();
//地图移动回去
moveMapBack();
//缩放已选框
mSelectedBox.setScale(0.65);
for (Plant plant : mSelectedPlants) {
plant.getShowPlant().setScale(0.65f); // 跟父容器同步缩小
plant.getShowPlant().setPosition(plant.getShowPlant().getPosition().x * 0.65f,
plant.getShowPlant().getPosition().y + (size.height - plant.getShowPlant().getPosition().y) * 0.35f);
this.addChild(plant.getShowPlant());
}
}
/**
* 10.地图反向移动
*/
private void moveMapBack(){
float offset = map.getContentSize().width - size.width; // 地图移动的偏移量
CCDelayTime delay = CCDelayTime.action(1); // 延时1秒
CCMoveBy move = CCMoveBy.action(2,ccp(offset,0));
CCSequence sequence = CCSequence.actions(delay,move,delay,CCCallFunc.action(this,"showLabel"));
map.runAction(sequence);
}
/**
* 11.游戏开始前的文字展示
*/
public void showLabel(){
//回收僵尸,节省内存
for (Zombie zombie : mShowZombies) {
zombie.removeSelf();
}
mShowZombies.clear();
//显示准备开始战斗的文字
startLabel = CCSprite.sprite("image/fight/startready_01.png");
startLabel.setPosition(size.width / 2 , size.height / 2);
this.addChild(startLabel);
CCAnimate animate = (CCAnimate) CommonUtil.animate("image/fight/startready_%02d.png", 3, false,0.5f);
CCSequence sequence = CCSequence.actions(animate,CCCallFunc.action(this,"gameStart"));
startLabel.runAction(sequence);
}
/**
* 12.游戏正式开始的处理
*/
public void gameStart(){
startLabel.removeSelf();
System.out.println("游戏正式开始");
GameEngine.getInstance().gameStart(map,mSelectedPlants);
}
}
base目录下的文件如图所示:
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.util.CGPointUtil;
/**
* 普通僵尸的实体类
*/
public class PrimaryZombie extends Zombie {
public PrimaryZombie(CGPoint startPoint,CGPoint endPoint) {
super("image/zombies/zombies_1/walk/z_1_01.png");
this.startPoint = startPoint;
this.endPoint = endPoint;
this.setPosition(startPoint); // 设置僵尸起点坐标
move();
}
@Override
public void move() {
CCMoveTo move = CCMoveTo.action(CGPointUtil.distance(startPoint,endPoint) / speed,endPoint);
this.runAction(move);
baseAction();
}
@Override
public void attack(BaseElement element) {
}
@Override
public void attacked(int attack) {
}
@Override
public void baseAction() {
// 僵尸行走
CCAction move = CommonUtil.animate("image/zombies/zombies_1/walk/z_1_%02d.png", 7, true);
this.runAction(move);
}
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.PrimaryZombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
/**
* 僵尸的移动路径
*/
private ArrayList<CGPoint> mZombiePoints;
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
mZombiePoints = CommonUtil.loadPoint(map, "road");
loadZombie();
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
}
/**
* 3.加载僵尸
*/
private void loadZombie() {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
}
}
package com.example.zombievsplantdemo;
import android.app.Activity;
import android.os.Bundle;
import com.example.zombievsplantdemo.layer.FightLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.opengl.CCGLSurfaceView;
import org.cocos2d.sound.SoundEngine;
public class MainActivity extends Activity {
/**
* 导演
*/
CCDirector director = CCDirector.sharedDirector();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//调用顺序:视图(CCGLSurfaceView) -》 导演(CCDirector) -》 场景(CCScene) -》 图层(CCLayer) -》 精灵(CCSprite) -》 动作(CCMove)
// 获取视图
CCGLSurfaceView view = new CCGLSurfaceView(this); // 创建一个SurfaceView,类似导演眼前的小屏幕,必须传this,底层要强转成Actvity
setContentView(view);
// 获取导演的单例对象
director.attachInView(view); // 开启绘制线程的方法
director.setDisplayFPS(true); // 显示帧率,表示每秒刷新页面的次数。一般当帧率大于30帧时,基本上人眼看起来比较流畅,帧率和手机性能与程序性能有关
//director.setAnimationInterval(1/60f); // 设置最高帧率位60
director.setDeviceOrientation(CCDirector.kCCDeviceOrientationLandscapeLeft); // 设置屏幕方式为横屏显示
director.setScreenSize(480,320); // 设置分辨率,用于屏幕适配,会基于不同大小的屏幕等比例缩放,设置我们开发时候的分辨率
// 获取场景对象
CCScene scene = CCScene.node();
// 获取图层对象
//FirstLayer layer = new FirstLayer();
//ActionLayer layer = new ActionLayer();
FightLayer layer = new FightLayer();
// 配置环境
scene.addChild(layer); // 给场景添加图层
director.runWithScene(scene); // 导演运行场景
}
@Override
protected void onResume() {
super.onResume();
director.resume(); // 游戏继续
SoundEngine.sharedEngine().resumeSound(); // 音乐继续
}
@Override
protected void onPause() {
super.onPause();
director.pause(); // 游戏暂停
SoundEngine.sharedEngine().pauseSound(); // 音乐暂停
}
@Override
protected void onDestroy() {
super.onDestroy();
director.end(); // 游戏结束
System.exit(0); // 退出游戏时杀死程序的进程,清空所有静态变量
}
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.PrimaryZombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.types.CGPoint;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
/**
* 僵尸的移动路径
*/
private ArrayList<CGPoint> mZombiePoints;
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
mZombiePoints = CommonUtil.loadPoint(map, "road");
// 定时器
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("loadZombie",this,2,false); //每隔两秒执行一次loadZombie()方法
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
}
/**
* 3.加载僵尸
* @param f 必须有的参数,不然CCScheduler无法通过反射调用
*/
public void loadZombie(float f) {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.util.CGPointUtil;
/**
* 普通僵尸的实体类
*/
public class PrimaryZombie extends Zombie {
public PrimaryZombie(CGPoint startPoint,CGPoint endPoint) {
super("image/zombies/zombies_1/walk/z_1_01.png");
this.startPoint = startPoint;
this.endPoint = endPoint;
this.setPosition(startPoint); // 设置僵尸起点坐标
move();
}
@Override
public void move() {
CCMoveTo move = CCMoveTo.action(CGPointUtil.distance(startPoint,endPoint) / speed,endPoint);
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"destroy")); // 僵尸走到头要销毁
this.runAction(sequence);
baseAction();
}
@Override
public void attack(BaseElement element) {
}
@Override
public void attacked(int attack) {
}
@Override
public void baseAction() {
// 僵尸行走
CCAction move = CommonUtil.animate("image/zombies/zombies_1/walk/z_1_%02d.png", 7, true);
this.runAction(move);
}
}
/**
* 已选植物的标志位
*/
public static final int TAG_SELECTED_BOX = 1;
/**
* 5.展示植物选择框(已选)
*/
private void showSelectedBox(){
mSelectedBox = CCSprite.sprite("image/fight/chose/fight_chose.png");
mSelectedBox.setAnchorPoint(0,1); // 设置锚点为左上角
mSelectedBox.setPosition(0,size.height);
this.addChild(mSelectedBox,0,TAG_SELECTED_BOX);
}
另外,修改gamePrepare()方法,在其中关闭图层触摸开关,防止出现Bug,代码如下:
/**
* 9.点击“开始战斗”后,游戏资源的准备
*/
private void gamePrepare(){
setIsTouchEnabled(false); // 禁用点击事件
//隐藏植物框
mChooseBox.removeSelf();
//地图移动回去
moveMapBack();
//缩放已选框
mSelectedBox.setScale(0.65);
for (Plant plant : mSelectedPlants) {
plant.getShowPlant().setScale(0.65f); // 跟父容器同步缩小
plant.getShowPlant().setPosition(plant.getShowPlant().getPosition().x * 0.65f,
plant.getShowPlant().getPosition().y + (size.height - plant.getShowPlant().getPosition().y) * 0.35f);
this.addChild(plant.getShowPlant());
}
}
最后,修改gameStart()方法,在地图移动完毕之后重新启用图层触摸开关,代码如下:
/**
* 12.游戏正式开始的处理
*/
public void gameStart(){
startLabel.removeSelf();
System.out.println("游戏正式开始");
setIsTouchEnabled(true); // 打开点击事件
GameEngine.getInstance().gameStart(map,mSelectedPlants);
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.PrimaryZombie;
import com.example.zombievsplantdemo.layer.FightLayer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
/**
* 僵尸的移动路径
*/
private ArrayList<CGPoint> mZombiePoints;
/**
* 当前被选择的植物
*/
private Plant mShowPlant;
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
mZombiePoints = CommonUtil.loadPoint(map, "road");
// 定时器
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("loadZombie",this,2,false); //每隔两秒执行一次loadZombie()方法
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
CGPoint point = map.convertTouchToNodeSpace(event);
CCSprite selectedBox = (CCSprite) map.getParent().getChildByTag(FightLayer.TAG_SELECTED_BOX);
if (CGRect.containsPoint(selectedBox.getBoundingBox(),point)){ // 已选框被点击
for (Plant plant : mSelectedPlants) {
if (CGRect.containsPoint(plant.getShowPlant().getBoundingBox(),point)){
mShowPlant = plant;
plant.getShowPlant().setOpacity(100);//变为半透明
break;
}
}
}
}
/**
* 3.加载僵尸
* @param f 必须有的参数,不然CCScheduler无法通过反射调用
*/
public void loadZombie(float f) {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.DefancePlant;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
/**
* 土豆的实体类
*/
public class Nut extends DefancePlant {
public Nut() {
super("image/plant/nut/p_3_01.png");
baseAction();
}
@Override
public void baseAction() {
CCAction animate = CommonUtil.animate("image/plant/nut/p_3_%02d.png", 11, true);
this.runAction(animate);
}
}
package com.example.zombievsplantdemo.domain;
import org.cocos2d.nodes.CCSprite;
/**
* 植物的实体类
*/
public class Plant {
/**
* 植物图标
*/
private String format = "image/fight/chose/choose_default%02d.png";
/**
* 背景图片(半透明)
*/
private CCSprite bgPlant;
/**
* 背景图片(展现)
*/
private CCSprite showPlant;
/**
* 标识植物的种类
*/
private int id;
public Plant(int i) {
this.id = i;
initBgPlant(i);
initShowPlant(i);
}
/**
* 初始化植物背景图标(半透明)
* @param i 植物图标的序号
*/
private void initBgPlant(int i){
bgPlant = CCSprite.sprite(String.format(format,i));
float x = (i - 1) % 4 * 54 + 16; // 计算x坐标
float y = 175 - (i - 1) / 4 * 59; // 计算y坐标
bgPlant.setAnchorPoint(0,0); // 设置锚点为左下角
bgPlant.setPosition(x,y);
bgPlant.setOpacity(100); // 设置为半透明
}
/**
* 初始化植物背景图标(展现)
* @param i 植物图标的序号
*/
private void initShowPlant(int i){
showPlant = CCSprite.sprite(String.format(format,i));
float x = (i - 1) % 4 * 54 + 16; // 计算x坐标
float y = 175 - (i - 1) / 4 * 59; // 计算y坐标
showPlant.setAnchorPoint(0,0); // 设置锚点为左下角
showPlant.setPosition(x,y);
}
public CCSprite getBgPlant() {
return bgPlant;
}
public CCSprite getShowPlant() {
return showPlant;
}
public int getId() {
return id;
}
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Nut;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.PrimaryZombie;
import com.example.zombievsplantdemo.layer.FightLayer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
/**
* 僵尸的移动路径
*/
private ArrayList<CGPoint> mZombiePoints;
/**
* 当前被点击的植物
*/
private Plant mShowPlant;
/**
* 当前被安放的植物
*/
private com.example.zombievsplantdemo.domain.base.Plant mPlant;
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
mZombiePoints = CommonUtil.loadPoint(map, "road");
// 定时器
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("loadZombie",this,2,false); //每隔两秒执行一次loadZombie()方法
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
CGPoint point = map.convertTouchToNodeSpace(event);
CCSprite selectedBox = (CCSprite) map.getParent().getChildByTag(FightLayer.TAG_SELECTED_BOX);
if (CGRect.containsPoint(selectedBox.getBoundingBox(),point)){ // 已选框被点击
for (Plant plant : mSelectedPlants) {
if (CGRect.containsPoint(plant.getShowPlant().getBoundingBox(),point)){
mShowPlant = plant;
plant.getShowPlant().setOpacity(100);//变为半透明
switch (mShowPlant.getId()){
case 4:
mPlant = new Nut(); // 安放土豆
break;
default:
break;
}
break;
}
}
}else { //鼠标落在草坪上
if (isInGrass(point)){ // 判断是否落在草坪的格子里
System.out.println("在格子里");
}
}
}
/**
* 3.加载僵尸
* @param f 必须有的参数,不然CCScheduler无法通过反射调用
*/
public void loadZombie(float f) {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
}
/**
* 4.判断是否在草坪的格子上
* @return
*/
private boolean isInGrass(CGPoint point){
int column = (int) (point.x / 46); // 计算第几列
int line = (int) ((CCDirector.sharedDirector().winSize().height - point.y) / 54); // 计算第几行
if (column >= 1 && column <= 9 && line >= 1 && line <= 5){
return true;
}
return false;
}
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Nut;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.PrimaryZombie;
import com.example.zombievsplantdemo.layer.FightLayer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
/**
* 僵尸的移动路径
*/
private ArrayList<CGPoint> mZombiePoints;
/**
* 当前被点击的植物
*/
private Plant mShowPlant;
/**
* 当前被安放的植物
*/
private com.example.zombievsplantdemo.domain.base.Plant mPlant;
/**
* 存放植物坐标的二维数组
*/
private CGPoint[][] mPlantPoints = new CGPoint[5][9];
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
mZombiePoints = CommonUtil.loadPoint(map, "road");
// 定时器
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("loadZombie",this,2,false); //每隔两秒执行一次loadZombie()方法
loadPlant();
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
CGPoint point = map.convertTouchToNodeSpace(event);
CCSprite selectedBox = (CCSprite) map.getParent().getChildByTag(FightLayer.TAG_SELECTED_BOX);
if (CGRect.containsPoint(selectedBox.getBoundingBox(),point)){ // 已选框被点击
for (Plant plant : mSelectedPlants) {
if (CGRect.containsPoint(plant.getShowPlant().getBoundingBox(),point)){
if (mShowPlant != null){
mShowPlant.getShowPlant().setOpacity(255); // 将上一个植物设置为不透明
}
mShowPlant = plant;
plant.getShowPlant().setOpacity(100);//变为半透明
switch (mShowPlant.getId()){
case 4:
mPlant = new Nut(); // 安放土豆
break;
default:
break;
}
break;
}
}
}else { //鼠标落在草坪上
if (isInGrass(point)){ // 判断是否落在草坪的格子里
System.out.println("在格子里");
if (mPlant != null && mShowPlant != null){
map.addChild(mPlant); // 植物已经安放好了
mShowPlant.getShowPlant().setOpacity(255); // 安放完毕后,透明度编程完全不透明
mPlant = null;
mShowPlant = null;
}
}
}
}
/**
* 3.加载僵尸
* @param f 必须有的参数,不然CCScheduler无法通过反射调用
*/
public void loadZombie(float f) {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
}
/**
* 4.判断是否在草坪的格子上
* @return
*/
private boolean isInGrass(CGPoint point){
int column = (int) (point.x / 46); // 计算第几列
int line = (int) ((CCDirector.sharedDirector().winSize().height - point.y) / 54); // 计算第几行
if (column >= 1 && column <= 9 && line >= 1 && line <= 5){
if (mPlant != null){
mPlant.setLine(line - 1); // 设置行号
mPlant.setColumn(column - 1); // 设置列号
mPlant.setPosition(mPlantPoints[line-1][column-1]); // 设置植物的位置
return true;
}
}
return false;
}
/**
* 5.加载植物
*/
private void loadPlant() {
String format = "tower%02d";
for (int i = 1; i <= 5; i++) {
ArrayList<CGPoint> loadPoints = CommonUtil.loadPoint(map, String.format(format, i));
for (int j = 0; j < loadPoints.size() ; j++) {
mPlantPoints[i-1][j] = loadPoints.get(j);
}
}
}
}
package com.example.zombievsplantdemo.engine;
import com.example.zombievsplantdemo.domain.base.Plant;
import java.util.HashMap;
/**
* 封装战线的引擎类
*/
public class FightLineEngine {
public FightLineEngine(int i) {
}
/**
* 保存植物对象的Map
*/
private HashMap<Integer,Plant> mPlants = new HashMap<>(); // key表示植物在第几列
/**
* 添加植物
* @param plant 植物对象
*/
public void addPlant(Plant plant){
mPlants.put(plant.getColumn(),plant);
}
/**
* 判断战线上是否已经有植物,有的话就不能再安放了
* @return
*/
public boolean contaionsPlant(Plant plant){
return mPlants.keySet().contains(plant.getColumn());
}
}
package com.example.zombievsplantdemo.engine;
import android.view.MotionEvent;
import com.example.zombievsplantdemo.domain.Nut;
import com.example.zombievsplantdemo.domain.Plant;
import com.example.zombievsplantdemo.domain.PrimaryZombie;
import com.example.zombievsplantdemo.layer.FightLayer;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.layers.CCTMXTiledMap;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 处理战斗逻辑的引擎
* 单例类
*/
public class GameEngine {
/**
* 单例对象
*/
private static GameEngine mInstance = new GameEngine();
/**
* 游戏地图
*/
private CCTMXTiledMap map;
/**
* 已选植物
*/
private CopyOnWriteArrayList<Plant> mSelectedPlants;
/**
* 标记游戏是否正式开始
*/
public static boolean isStart;
/**
* 僵尸的移动路径
*/
private ArrayList<CGPoint> mZombiePoints;
/**
* 当前被点击的植物
*/
private Plant mShowPlant;
/**
* 当前被安放的植物
*/
private com.example.zombievsplantdemo.domain.base.Plant mPlant;
/**
* 存放植物坐标的二维数组
*/
private CGPoint[][] mPlantPoints = new CGPoint[5][9];
/**
* 存储战线集合
*/
private static ArrayList<FightLineEngine> mFightLines;
/**
* 初始化5条战线
*/
static {
mFightLines = new ArrayList<>();
for (int i = 0; i < 5; i++) {
FightLineEngine line = new FightLineEngine(i);
mFightLines.add(line);
}
}
public GameEngine() {
}
public static GameEngine getInstance(){
return mInstance;
}
/**
* 1.游戏开始的一些处理
* @param map 游戏地图
* @param selectedPlants 已选植物
*/
public void gameStart(CCTMXTiledMap map,CopyOnWriteArrayList<Plant> selectedPlants){
isStart = true;
this.map = map;
this.mSelectedPlants = selectedPlants;
mZombiePoints = CommonUtil.loadPoint(map, "road");
// 定时器
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("loadZombie",this,2,false); //每隔两秒执行一次loadZombie()方法
loadPlant();
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
CGPoint point = map.convertTouchToNodeSpace(event);
CCSprite selectedBox = (CCSprite) map.getParent().getChildByTag(FightLayer.TAG_SELECTED_BOX);
if (CGRect.containsPoint(selectedBox.getBoundingBox(),point)){ // 已选框被点击
for (Plant plant : mSelectedPlants) {
if (CGRect.containsPoint(plant.getShowPlant().getBoundingBox(),point)){
if (mShowPlant != null){
mShowPlant.getShowPlant().setOpacity(255); // 将上一个植物设置为不透明
}
mShowPlant = plant;
plant.getShowPlant().setOpacity(100);//变为半透明
switch (mShowPlant.getId()){
case 4:
mPlant = new Nut(); // 安放土豆
break;
default:
break;
}
break;
}
}
}else { //鼠标落在草坪上
if (isInGrass(point)){ // 判断是否落在草坪的格子里
System.out.println("在格子里");
if (mPlant != null && mShowPlant != null){
map.addChild(mPlant); // 植物已经安放好了
mShowPlant.getShowPlant().setOpacity(255); // 安放完毕后,透明度编程完全不透明
//给战线添加植物
mFightLines.get(mPlant.getLine()).addPlant(mPlant);
mPlant = null;
mShowPlant = null;
}
}
}
}
/**
* 3.加载僵尸
* @param f 必须有的参数,不然CCScheduler无法通过反射调用
*/
public void loadZombie(float f) {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
}
/**
* 4.判断是否在草坪的格子上
* @return
*/
private boolean isInGrass(CGPoint point){
int column = (int) (point.x / 46); // 计算第几列
int line = (int) ((CCDirector.sharedDirector().winSize().height - point.y) / 54); // 计算第几行
if (column >= 1 && column <= 9 && line >= 1 && line <= 5){
if (mPlant != null){
mPlant.setLine(line - 1); // 设置行号
mPlant.setColumn(column - 1); // 设置列号
mPlant.setPosition(mPlantPoints[line-1][column-1]); // 设置植物的位置
if (mFightLines.get(line - 1).contaionsPlant(mPlant)){ // 判断战线是否包含植物
return false;
}
return true;
}
}
return false;
}
/**
* 5.加载植物
*/
private void loadPlant() {
String format = "tower%02d";
for (int i = 1; i <= 5; i++) {
ArrayList<CGPoint> loadPoints = CommonUtil.loadPoint(map, String.format(format, i));
for (int j = 0; j < loadPoints.size() ; j++) {
mPlantPoints[i-1][j] = loadPoints.get(j);
}
}
}
}
package com.example.zombievsplantdemo.engine;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import org.cocos2d.actions.CCScheduler;
import java.util.HashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 封装战线的引擎类
*/
public class FightLineEngine {
/**
* 保存植物对象的Map
*/
private HashMap<Integer,Plant> mPlants = new HashMap<>(); // key表示植物在第几列
/**
* 保存僵尸对象的集合
*/
private CopyOnWriteArrayList<Zombie> mZombies = new CopyOnWriteArrayList<>();
public FightLineEngine(int i) {
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,0.2f,false);
}
/**
* 1.添加植物
* @param plant 植物对象
*/
public void addPlant(Plant plant){
mPlants.put(plant.getColumn(),plant);
}
/**
* 2.判断战线上是否已经有植物,有的话就不能再安放了
* @return
*/
public boolean contaionsPlant(Plant plant){
return mPlants.keySet().contains(plant.getColumn());
}
/**
* 3.添加僵尸
* @param zombie 僵尸对象
*/
public void addZombie(final Zombie zombie){
// 僵尸的死亡回调
zombie.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mZombies.remove(zombie); // 僵尸死亡后从集合中移除
}
});
mZombies.add(zombie);
}
/**
* 4.僵尸攻击植物
* @param f
*/
public void attackPlant(float f){
}
}
/**
* 3.加载僵尸
* @param f 必须有的参数,不然CCScheduler无法通过反射调用
*/
public void loadZombie(float f) {
Random random = new Random();
int line = random.nextInt(5); // 随机数为0,1,2,3,4
CGPoint startPoint = mZombiePoints.get(line * 2); // 起点坐标
CGPoint endPoint = mZombiePoints.get(line * 2 + 1); // 终点坐标
PrimaryZombie zombie = new PrimaryZombie(startPoint,endPoint);
map.addChild(zombie);
mFightLines.get(line).addZombie(zombie); // 把僵尸添加到战线中
}
package com.example.zombievsplantdemo.engine;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import org.cocos2d.actions.CCScheduler;
import java.util.HashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 封装战线的引擎类
*/
public class FightLineEngine {
/**
* 保存植物对象的Map
*/
private HashMap<Integer,Plant> mPlants = new HashMap<>(); // key表示植物在第几列
/**
* 保存僵尸对象的集合
*/
private CopyOnWriteArrayList<Zombie> mZombies = new CopyOnWriteArrayList<>();
public FightLineEngine(int i) {
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,0.2f,false); // 每隔0.2秒检测僵尸是否可以攻击植物
}
/**
* 1.添加植物
* @param plant 植物对象
*/
public void addPlant(Plant plant){
mPlants.put(plant.getColumn(),plant);
}
/**
* 2.判断战线上是否已经有植物,有的话就不能再安放了
* @return
*/
public boolean contaionsPlant(Plant plant){
return mPlants.keySet().contains(plant.getColumn());
}
/**
* 3.添加僵尸
* @param zombie 僵尸对象
*/
public void addZombie(final Zombie zombie){
// 僵尸的死亡回调
zombie.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mZombies.remove(zombie); // 僵尸死亡后从集合中移除
}
});
mZombies.add(zombie);
}
/**
* 4.僵尸攻击植物
* @param f
*/
public void attackPlant(float f){
if (!mPlants.isEmpty() && !mZombies.isEmpty()){
for (Zombie zombie : mZombies) {
int column = (int) (zombie.getPosition().x / 46 - 1) ;
if(mPlants.keySet().contains(column)){ // 僵尸当前所在的列上有植物存在
if (!zombie.isAttacking()){
zombie.attack(mPlants.get(column));// 表示僵尸开始攻击该列的植物
zombie.setAttacking(true); // 标记正在攻击
}
}
}
}
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.util.CGPointUtil;
/**
* 普通僵尸的实体类
*/
public class PrimaryZombie extends Zombie {
/**
* 正在被攻击的植物对象
*/
private Plant mPlant;
public PrimaryZombie(CGPoint startPoint,CGPoint endPoint) {
super("image/zombies/zombies_1/walk/z_1_01.png");
this.startPoint = startPoint;
this.endPoint = endPoint;
this.setPosition(startPoint); // 设置僵尸起点坐标
move();
}
@Override
public void move() {
CCMoveTo move = CCMoveTo.action(CGPointUtil.distance(startPoint,endPoint) / speed,endPoint);
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"destroy")); // 僵尸走到头要销毁
this.runAction(sequence);
baseAction();
}
@Override
public void attack(BaseElement element) {
if (element instanceof Plant){ // 判断元素是否是植物
mPlant = (Plant) element;
this.stopAllActions(); // 停止僵尸所有的动作
CCAction animate = CommonUtil.animate("image/zombies/zombies_1/attack/z_1_attack_%02d.png", 10, true);
this.runAction(animate); // 僵尸开始攻击植物的动画
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,1,false); // 每隔一秒钟咬一口植物
}
}
@Override
public void attacked(int attack) {
}
@Override
public void baseAction() {
// 僵尸行走
CCAction move = CommonUtil.animate("image/zombies/zombies_1/walk/z_1_%02d.png", 7, true);
this.runAction(move);
}
/**
* 1.僵尸攻击植物,植物掉血
* @param f 必须参数
*/
public void attackPlant(float f){
if (mPlant != null){
mPlant.attacked(attack); // 植物掉血
if (mPlant.getLife() <= 0){ // 植物死亡
CCScheduler.sharedScheduler().unschedule("attackPlant",this); // 停止定时器
this.stopAllActions();
move(); // 僵尸继续前进
isAttacking = false; // 表示僵尸已经攻击结束
}
}
}
}
/**
* 1.添加植物
* @param plant 植物对象
*/
public void addPlant(final Plant plant){
plant.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mPlants.remove(plant.getColumn()); // 移除植物
}
});
mPlants.put(plant.getColumn(),plant);
}
修改PrimaryZombie,为了解决僵尸在攻击完植物后速度不一致的问题,需要修改move()方法中的起始点,从startPoint更改为getPosition()即可,代码如下:
@Override
public void move() {
CCMoveTo move = CCMoveTo.action(CGPointUtil.distance(getPosition(),endPoint) / speed,endPoint);
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"destroy")); // 僵尸走到头要销毁
this.runAction(sequence);
baseAction();
}
在domain包下新建PeaPlant,代表豌豆射手的实体类,继承AttackPlant,代码如下:
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.AttackPlant;
import com.example.zombievsplantdemo.domain.base.Bullet;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.base.CCAction;
/**
* 豌豆射手的实体类
*/
public class PeaPlant extends AttackPlant {
public PeaPlant() {
super("image/plant/peas/p_2_01.png");
baseAction();
}
@Override
public Bullet createBullet() {
return null;
}
@Override
public void baseAction() {
CCAction animate = CommonUtil.animate("image/plant/peas/p_2_%02d.png", 8, true);
this.runAction(animate);
}
}
/**
* 2.专门处理点击事件
* @param event
*/
public void handleTouch(MotionEvent event){
CGPoint point = map.convertTouchToNodeSpace(event);
CCSprite selectedBox = (CCSprite) map.getParent().getChildByTag(FightLayer.TAG_SELECTED_BOX);
if (CGRect.containsPoint(selectedBox.getBoundingBox(),point)){ // 已选框被点击
for (Plant plant : mSelectedPlants) {
if (CGRect.containsPoint(plant.getShowPlant().getBoundingBox(),point)){
if (mShowPlant != null){
mShowPlant.getShowPlant().setOpacity(255); // 将上一个植物设置为不透明
}
mShowPlant = plant;
plant.getShowPlant().setOpacity(100);//变为半透明
switch (mShowPlant.getId()){
case 1:
mPlant = new PeaPlant(); // 安放豌豆射手
break;
case 4:
mPlant = new Nut(); // 安放土豆
break;
default:
break;
}
break;
}
}
}else { //鼠标落在草坪上
if (isInGrass(point)){ // 判断是否落在草坪的格子里
System.out.println("在格子里");
if (mPlant != null && mShowPlant != null){
map.addChild(mPlant); // 植物已经安放好了
mShowPlant.getShowPlant().setOpacity(255); // 安放完毕后,透明度编程完全不透明
//给战线添加植物
mFightLines.get(mPlant.getLine()).addPlant(mPlant);
mPlant = null;
mShowPlant = null;
}
}
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.Bullet;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.nodes.CCDirector;
/**
* 豌豆射手的子弹的实体类
*/
public class Pea extends Bullet {
public Pea() {
super("image/fight/bullet.png");
setScale(0.65f);
}
@Override
public void move() {
float t = (CCDirector.sharedDirector().winSize().width - getPosition().x) / speed; // 计算子弹移动时间
CCMoveTo move = CCMoveTo.action(t,ccp(CCDirector.sharedDirector().winSize().width,getPosition().y)); // 子弹移动到屏幕右侧边缘
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"destroy")); // 子弹销毁
runAction(sequence);
}
}
@Override
public Bullet createBullet() {
if (bullets.size() < 1){ // 每次只能生产一个子弹
final Pea pea = new Pea();
pea.setPosition(ccp(getPosition().x + 30,getPosition().y + 45)); // 设置子弹的位置
pea.move(); // 子弹移动
pea.setDieListener(new DieListener() {
@Override
public void die() {
bullets.remove(pea); // 从集合中移除子弹
}
});
bullets.add(pea);
this.getParent().addChild(pea); // 子弹显示到屏幕上
return pea;
}
return null;
}
package com.example.zombievsplantdemo.engine;
import com.example.zombievsplantdemo.domain.base.AttackPlant;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import org.cocos2d.actions.CCScheduler;
import java.util.HashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 封装战线的引擎类
*/
public class FightLineEngine {
/**
* 保存植物对象的Map
*/
private HashMap<Integer,Plant> mPlants = new HashMap<>(); // key表示植物在第几列
/**
* 保存僵尸对象的集合
*/
private CopyOnWriteArrayList<Zombie> mZombies = new CopyOnWriteArrayList<>();
/**
* 保存攻击性植物的集合
*/
private CopyOnWriteArrayList<AttackPlant> mAttackPlants = new CopyOnWriteArrayList<>();
public FightLineEngine(int i) {
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,0.2f,false); // 每隔0.2秒检测僵尸是否可以攻击植物
scheduler.schedule("createBullet",this,0.2f,false); // 每隔0.2秒检测是否要产生子弹
}
/**
* 1.添加植物
* @param plant 植物对象
*/
public void addPlant(final Plant plant){
plant.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mPlants.remove(plant.getColumn()); // 移除植物
mAttackPlants.remove(plant);
}
});
mPlants.put(plant.getColumn(),plant);
if (plant instanceof AttackPlant){ // 判断是否是可攻击性的植物
mAttackPlants.add((AttackPlant)plant);
}
}
/**
* 2.判断战线上是否已经有植物,有的话就不能再安放了
* @return
*/
public boolean contaionsPlant(Plant plant){
return mPlants.keySet().contains(plant.getColumn());
}
/**
* 3.添加僵尸
* @param zombie 僵尸对象
*/
public void addZombie(final Zombie zombie){
// 僵尸的死亡回调
zombie.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mZombies.remove(zombie); // 僵尸死亡后从集合中移除
}
});
mZombies.add(zombie);
}
/**
* 4.僵尸攻击植物
* @param f
*/
public void attackPlant(float f){
if (!mPlants.isEmpty() && !mZombies.isEmpty()){
for (Zombie zombie : mZombies) {
int column = (int) (zombie.getPosition().x / 46 - 1) ;
if(mPlants.keySet().contains(column)){ // 僵尸当前所在的列上有植物存在
if (!zombie.isAttacking()){
zombie.attack(mPlants.get(column));// 表示僵尸开始攻击该列的植物
zombie.setAttacking(true); // 标记正在攻击
}
}
}
}
}
/**
* 5.产生子弹
* @param f
*/
public void createBullet(float f){
if (!mZombies.isEmpty() && !mAttackPlants.isEmpty()){ // 有僵尸和攻击性植物
for (AttackPlant plant : mAttackPlants) {
plant.createBullet(); // 产生子弹
}
}
}
}
package com.example.zombievsplantdemo.engine;
import com.example.zombievsplantdemo.domain.base.AttackPlant;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Bullet;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import org.cocos2d.actions.CCScheduler;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* 封装战线的引擎类
*/
public class FightLineEngine {
/**
* 保存植物对象的Map
*/
private HashMap<Integer,Plant> mPlants = new HashMap<>(); // key表示植物在第几列
/**
* 保存僵尸对象的集合
*/
private CopyOnWriteArrayList<Zombie> mZombies = new CopyOnWriteArrayList<>();
/**
* 保存攻击性植物的集合
*/
private CopyOnWriteArrayList<AttackPlant> mAttackPlants = new CopyOnWriteArrayList<>();
public FightLineEngine(int i) {
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,0.2f,false); // 每隔0.2秒检测僵尸是否可以攻击植物
scheduler.schedule("createBullet",this,0.2f,false); // 每隔0.2秒检测是否要产生子弹
scheduler.schedule("attackZombie",this,0.2f,false); // 每隔0.2秒检测子弹是否可以攻击僵尸
}
/**
* 1.添加植物
* @param plant 植物对象
*/
public void addPlant(final Plant plant){
plant.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mPlants.remove(plant.getColumn()); // 移除植物
mAttackPlants.remove(plant);
}
});
mPlants.put(plant.getColumn(),plant);
if (plant instanceof AttackPlant){ // 判断是否是可攻击性的植物
mAttackPlants.add((AttackPlant)plant);
}
}
/**
* 2.判断战线上是否已经有植物,有的话就不能再安放了
* @return
*/
public boolean contaionsPlant(Plant plant){
return mPlants.keySet().contains(plant.getColumn());
}
/**
* 3.添加僵尸
* @param zombie 僵尸对象
*/
public void addZombie(final Zombie zombie){
// 僵尸的死亡回调
zombie.setDieListener(new BaseElement.DieListener() {
@Override
public void die() {
mZombies.remove(zombie); // 僵尸死亡后从集合中移除
}
});
mZombies.add(zombie);
}
/**
* 4.僵尸攻击植物
* @param f
*/
public void attackPlant(float f){
if (!mPlants.isEmpty() && !mZombies.isEmpty()){
for (Zombie zombie : mZombies) {
int column = (int) (zombie.getPosition().x / 46 - 1) ;
if(mPlants.keySet().contains(column)){ // 僵尸当前所在的列上有植物存在
if (!zombie.isAttacking()){
zombie.attack(mPlants.get(column));// 表示僵尸开始攻击该列的植物
zombie.setAttacking(true); // 标记正在攻击
}
}
}
}
}
/**
* 5.产生子弹
* @param f
*/
public void createBullet(float f){
if (!mZombies.isEmpty() && !mAttackPlants.isEmpty()){ // 有僵尸和攻击性植物
for (AttackPlant plant : mAttackPlants) {
plant.createBullet(); // 产生子弹
}
}
}
/**
* 6.子弹攻击僵尸
* @param f
*/
public void attackZombie(float f){
if (!mZombies.isEmpty() && !mAttackPlants.isEmpty()){ // 有僵尸和攻击性植物
for (Zombie zombie : mZombies) {
int x = (int) zombie.getPosition().x;
int left = x - 10;
int right = x + 10;
for (AttackPlant plant : mAttackPlants) {
List<Bullet> bullets = plant.getBullets(); // 获取植物的子弹
for (Bullet bullet : bullets) {
int bx = (int) bullet.getPosition().x;
if (bx >= left && bx <= right){ // 子弹处于可攻击的范围内
zombie.attacked(bullet.getAttack()); // 僵尸掉血了
}
}
}
}
}
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.util.CGPointUtil;
/**
* 普通僵尸的实体类
*/
public class PrimaryZombie extends Zombie {
/**
* 正在被攻击的植物对象
*/
private Plant mPlant;
public PrimaryZombie(CGPoint startPoint,CGPoint endPoint) {
super("image/zombies/zombies_1/walk/z_1_01.png");
this.startPoint = startPoint;
this.endPoint = endPoint;
this.setPosition(startPoint); // 设置僵尸起点坐标
move();
}
@Override
public void move() {
CCMoveTo move = CCMoveTo.action(CGPointUtil.distance(getPosition(),endPoint) / speed,endPoint);
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"destroy")); // 僵尸走到头要销毁
this.runAction(sequence);
baseAction();
}
@Override
public void attack(BaseElement element) {
if (element instanceof Plant){ // 判断元素是否是植物
mPlant = (Plant) element;
this.stopAllActions(); // 停止僵尸所有的动作
CCAction animate = CommonUtil.animate("image/zombies/zombies_1/attack/z_1_attack_%02d.png", 10, true);
this.runAction(animate); // 僵尸开始攻击植物的动画
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,1,false); // 每隔一秒钟咬一口植物
}
}
@Override
public void attacked(int attack) {
life -= attack; // 僵尸掉血
if (life <= 0){
destroy(); // 僵尸死亡
}
}
@Override
public void baseAction() {
// 僵尸行走
CCAction move = CommonUtil.animate("image/zombies/zombies_1/walk/z_1_%02d.png", 7, true);
this.runAction(move);
}
/**
* 1.僵尸攻击植物,植物掉血
* @param f 必须参数
*/
public void attackPlant(float f){
if (mPlant != null){
mPlant.attacked(attack); // 植物掉血
if (mPlant.getLife() <= 0){ // 植物死亡
CCScheduler.sharedScheduler().unschedule("attackPlant",this); // 停止定时器
this.stopAllActions();
move(); // 僵尸继续前进
isAttacking = false; // 表示僵尸已经攻击结束
}
}
}
}
/**
* 6.子弹攻击僵尸
* @param f
*/
public void attackZombie(float f){
if (!mZombies.isEmpty() && !mAttackPlants.isEmpty()){ // 有僵尸和攻击性植物
for (Zombie zombie : mZombies) {
int x = (int) zombie.getPosition().x;
int left = x - 10;
int right = x + 10;
for (AttackPlant plant : mAttackPlants) {
List<Bullet> bullets = plant.getBullets(); // 获取植物的子弹
for (Bullet bullet : bullets) {
int bx = (int) bullet.getPosition().x;
if (bx >= left && bx <= right){ // 子弹处于可攻击的范围内
zombie.attacked(bullet.getAttack()); // 僵尸掉血了
bullet.setVisible(false); // 隐藏子弹
bullet.setAttack(0); // 让子弹攻击力为0
}
}
}
}
}
}
package com.example.zombievsplantdemo.domain;
import com.example.zombievsplantdemo.domain.base.BaseElement;
import com.example.zombievsplantdemo.domain.base.Plant;
import com.example.zombievsplantdemo.domain.base.Zombie;
import com.example.zombievsplantdemo.util.CommonUtil;
import org.cocos2d.actions.CCScheduler;
import org.cocos2d.actions.base.CCAction;
import org.cocos2d.actions.instant.CCCallFunc;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.util.CGPointUtil;
/**
* 普通僵尸的实体类
*/
public class PrimaryZombie extends Zombie {
/**
* 正在被攻击的植物对象
*/
private Plant mPlant;
/**
* 表示僵尸是否正在死亡
*/
private boolean isDieding = false;
public PrimaryZombie(CGPoint startPoint,CGPoint endPoint) {
super("image/zombies/zombies_1/walk/z_1_01.png");
this.startPoint = startPoint;
this.endPoint = endPoint;
this.setPosition(startPoint); // 设置僵尸起点坐标
move();
}
@Override
public void move() {
CCMoveTo move = CCMoveTo.action(CGPointUtil.distance(getPosition(),endPoint) / speed,endPoint);
CCSequence sequence = CCSequence.actions(move,CCCallFunc.action(this,"destroy")); // 僵尸走到头要销毁
this.runAction(sequence);
baseAction();
}
@Override
public void attack(BaseElement element) {
if (element instanceof Plant && !isDieding){ // 判断元素是否是植物
mPlant = (Plant) element;
this.stopAllActions(); // 停止僵尸所有的动作
CCAction animate = CommonUtil.animate("image/zombies/zombies_1/attack/z_1_attack_%02d.png", 10, true);
this.runAction(animate); // 僵尸开始攻击植物的动画
CCScheduler scheduler = CCScheduler.sharedScheduler();
scheduler.schedule("attackPlant",this,1,false); // 每隔一秒钟咬一口植物
}
}
@Override
public void attacked(int attack) {
life -= attack; // 僵尸掉血
if (life <= 0 && !isDieding){ // 没有攻击的动画
isDieding = true;
this.stopAllActions(); // 停止所有动画
if (!isAttacking){
CCAnimate animate1 = (CCAnimate) CommonUtil.animate("image/zombies/zombies_1/head/z_1_head_%02d.png", 6, false);
CCAnimate animate2 = (CCAnimate) CommonUtil.animate("image/zombies/zombies_1/die/z_1_die_%02d.png", 6, false);
CCSequence sequence = CCSequence.actions(animate1,animate2,CCCallFunc.action(this,"died"));
this.runAction(sequence);
}else { // 正在攻击的动画
CCAnimate animate3 = (CCAnimate) CommonUtil.animate("image/zombies/zombies_1/attack_losthead/z_1_attack_losthead_%02d.png", 8, false);
CCAnimate animate4 = (CCAnimate) CommonUtil.animate("image/zombies/zombies_1/die/z_1_die_%02d.png", 6, false);
CCSequence sequence = CCSequence.actions(animate3,animate4,CCCallFunc.action(this,"died"));
this.runAction(sequence);
}
}
}
@Override
public void baseAction() {
// 僵尸行走
CCAction move = CommonUtil.animate("image/zombies/zombies_1/walk/z_1_%02d.png", 7, true);
this.runAction(move);
}
/**
* 1.僵尸攻击植物,植物掉血
* @param f 必须参数
*/
public void attackPlant(float f){
if (mPlant != null && !isDieding){
mPlant.attacked(attack); // 植物掉血
if (mPlant.getLife() <= 0){ // 植物死亡
CCScheduler.sharedScheduler().unschedule("attackPlant",this); // 停止定时器
this.stopAllActions();
move(); // 僵尸继续前进
isAttacking = false; // 表示僵尸已经攻击结束
}
}else {
CCScheduler.sharedScheduler().unschedule("attackPlant",this); // 僵尸停止攻击植物
}
}