文章目录

1.游戏引擎Cocos2D

游戏引擎是指一些已编写好的可编辑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始。

这里要学习的Cocos2d-android,就是一款游戏引擎。

cocos2d是一个开源的游戏开发框架,利用它可以非常容易的开发2D游戏。 包括以下成员:

  • Cocos2d-x
  • Cocos2d-iphone
  • Cocos2d-android
  • 共同点:api名字基本一致
  • 本质区别:开发的语言不一样
  • Cocos2d-x使用c++
  • Cocos2d-iphone使用Object-C

Cocos2d的优点如下:

  • 一款开源的,跨平台,轻量级的2D游戏引擎。
  • 性能良好
  • 广泛的社区支持
  • 拥护很多成功案例。比如捕鱼达人、三国塔防等
  • 使用MIT授权协议。可以自由使用,修改源码,不需要像GPL一样公开源码,可以商用

Cocos2d的架构如图所示:

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_android

下面来详细介绍下Cocos2d的一些组件

2.图形引擎Cocos2D Graphic

Cocos2D Graphic引擎的架构图如下所示:

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_2d_02

之前用SurfaceView做游戏,就像放电影。而使用cocos2D开发游戏,就像拍电影

拍电影需要以下几个要素:

  • 导演:CCDirector,引擎的控制者,控制场景的切换,游戏引擎属性的设置
  • 场景:CCScene,场景类,例如游戏的闪屏,主菜单,游戏主界面等
  • 布景:CCLayer,图SAD层类,每个图层都有自己的触发事件,该事件只能对其拥有的元素有效,而图层之上的元素所包含的元素,是不受其事件管理的 D类,界面上显示的最小单元
  • 绘制物:CCNode,引擎中最重要的元素,所有可以被绘制的东西都是派生于此。它可以包含其它CCNode,可以执行定时器操作,可以执行CCAction
  • 动作:CCAction,动作类,如平移、缩放、旋转等动作

它们之间的结构图如下:

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_android_03

下面就让我们新建一个工程,开始尝试使用Cocos2D吧

3.实践一

这次,我们使用Cocos2D来制作一款移动端上很热门的游戏《植物大战僵尸》

  1. 导入cocos2d-android.jar,放入libs中,右键选择“add as library”,将jar包导入到项目中,如图所示:

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_2d_04


2. 修改MainActivvity,分别获取CCGLSurfaceView、CCDirector、CCLayer、CCScene对象,代码如下:

package com.example.cocos2ddemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import org.cocos2d.layers.CCLayer;
import org.cocos2d.layers.CCScene;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.opengl.CCGLSurfaceView;

public class MainActivity extends AppCompatActivity {

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

// 获取视图
CCGLSurfaceView view = new CCGLSurfaceView(this); // 创建一个SurfaceView,类似导演眼前的小屏幕
setContentView(view);

// 获取导演的单例对象
CCDirector director = CCDirector.sharedDirector();
director.attachInView(view); // 开启绘制线程的方法

// 获取场景对象
CCScene scene = CCScene.node();

// 获取图层对象
CCLayer layer = CCLayer.node();

// 配置环境
scene.addChild(layer); // 给场景添加图层
director.runWithScene(scene); // 导演运行场景
}
}
  1. 新建一个FirstLayer,用于实现一个自定义的图层。**注意:Cocos2d下的所有资源文件,都必须放在assets目录下。另外,在assets目录下必须要有fps_images.png图片,用于显示帧率,否则程序会崩溃!**代码如下:
package com.example.cocos2ddemo;

import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCSprite;

/**
* 第一个图层
*/
public class FirstLayer extends CCLayer {

public FirstLayer() {
CCSprite sprite = CCSprite.sprite("z_1_attack_01.png"); // 参数表示图片在assets目录下的相对路径
this.addChild(sprite); // 添加一个精灵
}
}
  1. 修改MainActivity,以此让图层显示出来,代码如下:
package com.example.cocos2ddemo;

import android.app.Activity;
import android.os.Bundle;

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

public class MainActivity extends Activity {

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

// 获取视图
CCGLSurfaceView view = new CCGLSurfaceView(this); // 创建一个SurfaceView,类似导演眼前的小屏幕
setContentView(view);

// 获取导演的单例对象
CCDirector director = CCDirector.sharedDirector();
director.attachInView(view); // 开启绘制线程的方法

// 获取场景对象
CCScene scene = CCScene.node();

// 获取图层对象
FirstLayer layer = new FirstLayer();

// 配置环境
scene.addChild(layer); // 给场景添加图层
director.runWithScene(scene); // 导演运行场景
}
}

4.Cocos2D的坐标体系

cocos2D的默认坐标点,在屏幕的左下角,而不是我们常识的左上角。

为了调整图层的位置,引入一个锚点的概念。

锚点,类似于图钉,首先在墙上找好一个点,这个点就是图片的展示位置,默认(0.5,0.5),然后在图片上找好一个点,用来向墙上钉图片。锚点默认是中心位置

锚点的相对坐标解析如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CyT87nBs-1577952525676)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200101201457945.png)]

5.CCNode

在介绍锚点之后,接下来简单介绍一下CCNode,这里引入CCNode官方文档中的一段话

Anything thats gets drawn or contains things that get drawn is a CCNode.
The most popular CCNodes are: CCScene, CCLayer, CCSprite, CCMenu.

翻译为:所有可被绘制的东西, 或者可以包含可绘制东西的事物, 都认为是一个CCNode对象

在进行以下的实践之前,在assets目录下添加一张图片,图片如下:

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_游戏开发_05

6.实践二

  1. 修改FirstLayer,设置图层的锚点和图层的显示位置,代码如下:
package com.example.cocos2ddemo;

import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCSprite;

/**
* 第一个图层
*/
public class FirstLayer extends CCLayer {

public FirstLayer() {
CCSprite sprite = CCSprite.sprite("z_1_attack_01.png"); // 参数表示图片在assets目录下的相对路径

sprite.setAnchorPoint(0,0); // 设置锚点,默认是0.5,0.5
sprite.setPosition(ccp(100,0)); // 设置僵尸的显示位置
this.addChild(sprite); // 添加一个精灵
}
}
  1. 修改MainActivity,配置CCDirector的各项参数,并且在Activity的生命周期中添加相应的恢复、暂停和结束逻辑,代码如下:
package com.example.cocos2ddemo;

import android.app.Activity;
import android.os.Bundle;

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

public class MainActivity extends Activity {

/**
* 导演
*/
CCDirector director = CCDirector.sharedDirector();

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

// 获取视图
CCGLSurfaceView view = new CCGLSurfaceView(this); // 创建一个SurfaceView,类似导演眼前的小屏幕
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();

// 配置环境
scene.addChild(layer); // 给场景添加图层
director.runWithScene(scene); // 导演运行场景
}

@Override
protected void onResume() {
super.onResume();
director.resume(); // 游戏继续
}

@Override
protected void onPause() {
super.onPause();
director.pause(); // 游戏暂停
}

@Override
protected void onDestroy() {
super.onDestroy();
director.end(); // 游戏结束
}
}
  1. 修改FirstLayer,配置CCSprite的各项参数,代码如下:
package com.example.cocos2ddemo;

import android.view.MotionEvent;

import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CGPoint;
import org.cocos2d.types.CGRect;

/**
* 第一个图层
*/
public class FirstLayer extends CCLayer {

/**
* 定义标志位
*/
private static final int TAG = 1;

public FirstLayer() {
CCSprite sprite = CCSprite.sprite("z_1_attack_01.png"); // 参数表示图片在assets目录下的相对路径

sprite.setAnchorPoint(0,0); // 设置锚点为左下角,默认是0.5,0.5
sprite.setPosition(ccp(0,0)); // 设置僵尸的显示位置
//sprite.setFlipX(true); // 水平翻转
//sprite.setFlipY(true); // 垂直翻转
//sprite.setOpacity(0); // 设置不透明度,值的范围为0~255,0为不透明,25为完全透明
//sprite.setScale(2); // 设置宽高的缩放比例,宽高变为2倍,面积变为4倍
//this.addChild(sprite); // 添加一个精灵(1)
this.addChild(sprite,0,TAG); // 添加一个精灵(2)
// 再设置一个图层(僵尸)
// CCSprite sprite2 = CCSprite.sprite("z_1_attack_01.png"); // 参数表示图片在assets目录下的相对路径
// sprite2.setAnchorPoint(0,0); // 设置锚点为左下角,默认是0.5,0.5
// sprite2.setPosition(ccp(0,0)); // 设置僵尸的显示位置
// sprite2.setScale(2);
// this.addChild(sprite2); // 添加一个精灵(3),第二个参数表示为展现优先级,越大展示在越上面,默认为0

setIsTouchEnabled(true); // 打开点击事件,默认为关闭,为了避免误操作而导致bug
}

/**
* 监听点击事件
* @param event
* @return
*/
@Override
public boolean ccTouchesBegan(MotionEvent event) {
CGPoint cgPoint = convertTouchToNodeSpace(event); // 转化为cocos2d的坐标体系
CCSprite ccSprite = (CCSprite) this.getChildByTag(TAG); // 通过tag找到图层(僵尸)对象
// 判断该坐标点有没有落在图层(僵尸)的身上
if (CGRect.containsPoint(ccSprite.getBoundingBox(),cgPoint)){
//ccSprite.setVisible(false); // 隐藏图层(僵尸)
//ccSprite.removeSelf(); // 移除图层(僵尸)
}
return super.ccTouchesBegan(event);
}
}

7.CCAction

CCAction是一个重要的事件触发机制,其中包含以下几个种类

  • CCFiniteTimeAction:有限时间的动作
  • CCInstantAction:瞬时动作 //CCHide. CCShow
  • CCIntervalAction:延时动作
  • CCFollow:跟随
  • CCRepeatForever:循环
  • CCSpeed;速度

至于XXTo表示变化到某个绝对值,而xxBy则表示基于原来的状态,偏移多少个像素

8.实践三

  1. 新建ActionLayer,用于模拟图层(僵尸)的动画,代码如下:
package com.example.cocos2ddemo;

import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCSprite;

/**
* 动作图层
*/
public class ActionLayer extends CCLayer {

/**
* 图层(僵尸)对象
*/
private CCSprite sprite;

public ActionLayer() {
sprite = CCSprite.sprite("z_1_attack_01.png");
sprite.setAnchorPoint(ccp(0,0));
sprite.setPosition(0,100);
this.addChild(sprite);
moveTo();
}

/**
* 图层(僵尸)移动(1)绝对
*/
private void moveTo(){
CCMoveTo action = CCMoveTo.action(3,ccp(200,0));
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(2)相对
*/
private void moveBy(){
CCMoveBy action = CCMoveBy.action(3,ccp(200,0));
sprite.runAction(action);
}
}
  1. 修改MainActivity,使其不再使用FirstLayer,转而使用刚刚创建的ActionLayer,代码如下:
package com.example.cocos2ddemo;

import android.app.Activity;
import android.os.Bundle;

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

public class MainActivity extends Activity {

/**
* 导演
*/
CCDirector director = CCDirector.sharedDirector();

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

// 获取视图
CCGLSurfaceView view = new CCGLSurfaceView(this); // 创建一个SurfaceView,类似导演眼前的小屏幕
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();

// 配置环境
scene.addChild(layer); // 给场景添加图层
director.runWithScene(scene); // 导演运行场景
}

@Override
protected void onResume() {
super.onResume();
director.resume(); // 游戏继续
}

@Override
protected void onPause() {
super.onPause();
director.pause(); // 游戏暂停
}

@Override
protected void onDestroy() {
super.onDestroy();
director.end(); // 游戏结束
}
}
  1. 修改ActionLayer,实现一些Cocos2D封装的一些简单的动作效果,代码如下:
package com.example.cocos2ddemo;

import org.cocos2d.actions.ease.CCEaseOut;
import org.cocos2d.actions.interval.CCBezierBy;
import org.cocos2d.actions.interval.CCBlink;
import org.cocos2d.actions.interval.CCFadeIn;
import org.cocos2d.actions.interval.CCJumpBy;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCRotateBy;
import org.cocos2d.actions.interval.CCRotateTo;
import org.cocos2d.actions.interval.CCScaleTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CCBezierConfig;

/**
* 动作图层
*/
public class ActionLayer extends CCLayer {

/**
* 图层(僵尸)对象
*/
private CCSprite sprite;

public ActionLayer() {
sprite = CCSprite.sprite("z_1_attack_01.png");
sprite.setAnchorPoint(ccp(0,0));
sprite.setPosition(0,100);
this.addChild(sprite);
moveTo();
//moveBy();
//rotateTo();
//roteteBy();
//scale();
//jump();
//fade();
//bazier();
//ease();
//blink();
}

/**
* 闪烁
*/
private void blink(){
CCBlink action = CCBlink.action(10,50); // 第二个参数表示闪烁的次数
sprite.runAction(action);
}

/**
* 加速度
*/
private void ease(){
CCMoveBy move = CCMoveBy.action(5,ccp(200,0));
//CCEaseIn action = CCEaseIn.action(move,5); // 第二个参数表示速率,渐快
CCEaseOut action = CCEaseOut.action(move,5); // 第二个参数表示速率,渐慢
sprite.runAction(action);
}

/**
* 贝塞尔曲线
*/
private void bazier(){
CCBezierConfig config = new CCBezierConfig();
config.controlPoint_1 = ccp(100,50);
config.controlPoint_2 = ccp(150,100);
config.endPosition = ccp(200,50);
CCBezierBy action = CCBezierBy.action(3,config);
sprite.runAction(action);
}

/**
* 淡入淡出
*/
private void fade(){
CCFadeIn action = CCFadeIn.action(2); // 淡入
//CCFadeOut action2 = CCFadeOut.action(2); // 淡出
sprite.runAction(action);
}

/**
* 跳跃
*/
private void jump(){
CCJumpBy action = CCJumpBy.action(2,ccp(100,100),150,1); // 第三个参数表示跳跃最高点,第四个参数表示跳跃次数
//reverse():表示动作逆向执行
CCSequence sequence = CCSequence.actions(action,action.reverse());// 顺序执行一系列动作
sprite.runAction(sequence);
}

/**
* 缩放
*/
private void scale(){
CCScaleTo action = CCScaleTo.action(3,2); // 第二个参数表示缩放比例
sprite.runAction(action);
}

/**
* 图层(僵尸)旋转(1),达到一定角度,在例子中会走捷径(逆时针转90度)
*/
private void rotetaTo(){
CCRotateTo action = CCRotateTo.action(3,270);
sprite.setAnchorPoint(0.5f,0.5f);
sprite.runAction(action);
}

/**
* 图层(僵尸)旋转(2),偏移量,在例子走会转完(顺时针转270度)
*/
private void roteteBy(){
CCRotateBy action = CCRotateBy.action(3,270);
sprite.setAnchorPoint(0.5f,0.5f);
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(1)绝对,坐标
*/
private void moveTo(){
CCMoveTo action = CCMoveTo.action(3,ccp(200,0));
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(2)相对,偏移量
*/
private void moveBy(){
CCMoveBy action = CCMoveBy.action(3,ccp(200,0));
sprite.runAction(action);
}
}
  1. 修改ActionLayer,实现一些Cocos2D封装的一些复杂的动作效果(后空翻),代码如下:
package com.example.cocos2ddemo;

import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.ease.CCEaseOut;
import org.cocos2d.actions.interval.CCBezierBy;
import org.cocos2d.actions.interval.CCBlink;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCFadeIn;
import org.cocos2d.actions.interval.CCJumpBy;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCRotateBy;
import org.cocos2d.actions.interval.CCRotateTo;
import org.cocos2d.actions.interval.CCScaleTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.actions.interval.CCSpawn;
import org.cocos2d.actions.interval.CCTintBy;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCLabel;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.types.CCBezierConfig;
import org.cocos2d.types.CGSize;

/**
* 动作图层
*/
public class ActionLayer extends CCLayer {

/**
* 图层(僵尸)对象
*/
private CCSprite sprite;

public ActionLayer() {
sprite = CCSprite.sprite("z_1_attack_01.png");
sprite.setAnchorPoint(ccp(0,0));
sprite.setPosition(0,100);
this.addChild(sprite);
//moveTo();
//moveBy();
//rotateTo();
//roteteBy();
//scale();
//jump();
//fade();
//bazier();
//ease();
//blink();
//tint();
//demo();
}



/**
* 让图层(僵尸)进行后空翻
*/
private void demo(){
sprite.setAnchorPoint(0.5f,0.5f);
CCJumpBy jump = CCJumpBy.action(2,ccp(100,100),150,2);
CCDelayTime delay = CCDelayTime.action(1); // 延迟一秒钟,也是一个CCAction
CCRotateBy rotate = CCRotateBy.action(1,360);
CCSequence sequence1 = CCSequence.actions(delay,rotate); // 先延时,再旋转
CCSpawn spawn = CCSpawn.actions(jump,sequence1); // 多个动作同时执行
CCSequence sequence2 = CCSequence.actions(spawn,spawn.reverse());
CCRepeatForever repeat = CCRepeatForever.action(sequence2);
sprite.runAction(repeat);
}

/**
* 渐变
*/
private void tint(){
CCLabel label = CCLabel.labelWithString("渐变效果","hkbd.ttf",20); // 初始化一段文字,第二个参数表示字体类型,第三个参数表示字体大小
label.setColor(ccc3(100,50,0));
CGSize cgSize = CCDirector.sharedDirector().winSize(); // 通过导演拿到屏幕尺寸
label.setPosition(ccp(cgSize.width / 2 ,cgSize.height / 2));
this.addChild(label);
CCTintBy tint = CCTintBy.action(3,ccc3(50,-50,100));
CCSequence sequence = CCSequence.actions(tint,tint.reverse());
CCRepeatForever repeat = CCRepeatForever.action(sequence); // 动作永远循环
label.runAction(repeat);
}

/**
* 闪烁
*/
private void blink(){
CCBlink action = CCBlink.action(10,50); // 第二个参数表示闪烁的次数
sprite.runAction(action);
}

/**
* 加速度
*/
private void ease(){
CCMoveBy move = CCMoveBy.action(5,ccp(200,0));
//CCEaseIn action = CCEaseIn.action(move,5); // 第二个参数表示速率,渐快
CCEaseOut action = CCEaseOut.action(move,5); // 第二个参数表示速率,渐慢
sprite.runAction(action);
}

/**
* 贝塞尔曲线
*/
private void bazier(){
CCBezierConfig config = new CCBezierConfig();
config.controlPoint_1 = ccp(100,50);
config.controlPoint_2 = ccp(150,100);
config.endPosition = ccp(200,50);
CCBezierBy action = CCBezierBy.action(3,config);
sprite.runAction(action);
}

/**
* 淡入淡出
*/
private void fade(){
CCFadeIn action = CCFadeIn.action(2); // 淡入
//CCFadeOut action2 = CCFadeOut.action(2); // 淡出
sprite.runAction(action);
}

/**
* 跳跃
*/
private void jump(){
CCJumpBy action = CCJumpBy.action(2,ccp(100,100),150,1); // 第三个参数表示跳跃最高点,第四个参数表示跳跃次数
//action.reverse():表示动作逆向执行
CCSequence sequence = CCSequence.actions(action,action.reverse());// 顺序执行一系列动作
sprite.runAction(sequence);
}

/**
* 缩放
*/
private void scale(){
CCScaleTo action = CCScaleTo.action(3,2); // 第二个参数表示缩放比例
sprite.runAction(action);
}

/**
* 图层(僵尸)旋转(1),达到一定角度,在例子中会走捷径(逆时针转90度)
*/
private void rotetaTo(){
CCRotateTo action = CCRotateTo.action(3,270);
sprite.setAnchorPoint(0.5f,0.5f);
sprite.runAction(action);
}

/**
* 图层(僵尸)旋转(2),偏移量,在例子走会转完(顺时针转270度)
*/
private void roteteBy(){
CCRotateBy action = CCRotateBy.action(3,270);
sprite.setAnchorPoint(0.5f,0.5f);
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(1)绝对,坐标
*/
private void moveTo(){
CCMoveTo action = CCMoveTo.action(3,ccp(200,0));
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(2)相对,偏移量
*/
private void moveBy(){
CCMoveBy action = CCMoveBy.action(3,ccp(200,0));
sprite.runAction(action);
}
}

9.CCAnimate

CCAnimate是CCAction下的一个子类,表示帧动画。要想实现僵尸在移动时展现不同的动画,则需要使用到这个类,需要与CCAnimation、CCSprite进行联动

10.实践四

  1. 在实践之前,添加相应的素材(僵尸行走图),总共7张,如图所示:
  2. Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_cocos2d_06


  3. Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_2d_07

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_2d_08


Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_图层_09


Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_android_10

Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_图层_11


Cocos2d游戏开发学习记录——2.使用Cocos2D Graphic实现僵尸的移动_图层_12

  1. 修改ActionLayer,增加让图层(僵尸)行走的方法(move),代码如下:
package com.example.cocos2ddemo;

import org.cocos2d.actions.base.CCRepeatForever;
import org.cocos2d.actions.ease.CCEaseOut;
import org.cocos2d.actions.interval.CCAnimate;
import org.cocos2d.actions.interval.CCBezierBy;
import org.cocos2d.actions.interval.CCBlink;
import org.cocos2d.actions.interval.CCDelayTime;
import org.cocos2d.actions.interval.CCFadeIn;
import org.cocos2d.actions.interval.CCJumpBy;
import org.cocos2d.actions.interval.CCMoveBy;
import org.cocos2d.actions.interval.CCMoveTo;
import org.cocos2d.actions.interval.CCRotateBy;
import org.cocos2d.actions.interval.CCRotateTo;
import org.cocos2d.actions.interval.CCScaleTo;
import org.cocos2d.actions.interval.CCSequence;
import org.cocos2d.actions.interval.CCSpawn;
import org.cocos2d.actions.interval.CCTintBy;
import org.cocos2d.layers.CCLayer;
import org.cocos2d.nodes.CCAnimation;
import org.cocos2d.nodes.CCDirector;
import org.cocos2d.nodes.CCLabel;
import org.cocos2d.nodes.CCSprite;
import org.cocos2d.nodes.CCSpriteFrame;
import org.cocos2d.types.CCBezierConfig;
import org.cocos2d.types.CGSize;

import java.util.ArrayList;

/**
* 动作图层
*/
public class ActionLayer extends CCLayer {

/**
* 图层(僵尸)对象
*/
private CCSprite sprite;

public ActionLayer() {
sprite = CCSprite.sprite("z_1_attack_01.png");
sprite.setAnchorPoint(ccp(0,0));
sprite.setPosition(0,0);
this.addChild(sprite);
//moveTo();
//moveBy();
//rotateTo();
//roteteBy();
//scale();
//jump();
//fade();
//bazier();
//ease();
//blink();
//tint();
//demo();
walk();
}

/**
* 图层(僵尸)行走
*/
private void walk(){
sprite.setFlipX(true); // 水平翻转
CCMoveBy move = CCMoveBy.action(5,ccp(200,0));
sprite.runAction(move);

ArrayList<CCSpriteFrame> frames = new ArrayList<>();
String format = "z_1_%02d.png"; // %02d表示两位数字,如果是个位,用0去补位(01,02);如果是十位,则不用补位(10,11)
// 初始化7帧图片
for (int i = 1; i <= 7 ; i++) {
frames.add(CCSprite.sprite(String.format(format,i)).displayedFrame());
}

CCAnimation animation = CCAnimation.animation("walk",.2f,frames); // 第二个参数表示每一帧显示时间
CCAnimate animate = CCAnimate.action(animation);

CCRepeatForever repeat = CCRepeatForever.action(animate); // 表示动画永远循环,若不循环则会报出空指针异常

sprite.runAction(repeat);
}

/**
* 让图层(僵尸)进行后空翻
*/
private void demo(){
sprite.setAnchorPoint(0.5f,0.5f);
CCJumpBy jump = CCJumpBy.action(2,ccp(100,100),150,2);
CCDelayTime delay = CCDelayTime.action(1); // 延迟一秒钟,也是一个CCAction
CCRotateBy rotate = CCRotateBy.action(1,360);
CCSequence sequence1 = CCSequence.actions(delay,rotate); // 先延时,再旋转
CCSpawn spawn = CCSpawn.actions(jump,sequence1); // 多个动作同时执行
CCSequence sequence2 = CCSequence.actions(spawn,spawn.reverse());
CCRepeatForever repeat = CCRepeatForever.action(sequence2);
sprite.runAction(repeat);
}

/**
* 渐变
*/
private void tint(){
CCLabel label = CCLabel.labelWithString("渐变效果","hkbd.ttf",20); // 初始化一段文字,第二个参数表示字体类型,第三个参数表示字体大小
label.setColor(ccc3(100,50,0));
CGSize cgSize = CCDirector.sharedDirector().winSize(); // 通过导演拿到屏幕尺寸
label.setPosition(ccp(cgSize.width / 2 ,cgSize.height / 2));
this.addChild(label);
CCTintBy tint = CCTintBy.action(3,ccc3(50,-50,100));
CCSequence sequence = CCSequence.actions(tint,tint.reverse());
CCRepeatForever repeat = CCRepeatForever.action(sequence); // 动作永远循环
label.runAction(repeat);
}

/**
* 闪烁
*/
private void blink(){
CCBlink action = CCBlink.action(10,50); // 第二个参数表示闪烁的次数
sprite.runAction(action);
}

/**
* 加速度
*/
private void ease(){
CCMoveBy move = CCMoveBy.action(5,ccp(200,0));
//CCEaseIn action = CCEaseIn.action(move,5); // 第二个参数表示速率,渐快
CCEaseOut action = CCEaseOut.action(move,5); // 第二个参数表示速率,渐慢
sprite.runAction(action);
}

/**
* 贝塞尔曲线
*/
private void bazier(){
CCBezierConfig config = new CCBezierConfig();
config.controlPoint_1 = ccp(100,50);
config.controlPoint_2 = ccp(150,100);
config.endPosition = ccp(200,50);
CCBezierBy action = CCBezierBy.action(3,config);
sprite.runAction(action);
}

/**
* 淡入淡出
*/
private void fade(){
CCFadeIn action = CCFadeIn.action(2); // 淡入
//CCFadeOut action2 = CCFadeOut.action(2); // 淡出
sprite.runAction(action);
}

/**
* 跳跃
*/
private void jump(){
CCJumpBy action = CCJumpBy.action(2,ccp(100,100),150,1); // 第三个参数表示跳跃最高点,第四个参数表示跳跃次数
//action.reverse():表示动作逆向执行
CCSequence sequence = CCSequence.actions(action,action.reverse());// 顺序执行一系列动作
sprite.runAction(sequence);
}

/**
* 缩放
*/
private void scale(){
CCScaleTo action = CCScaleTo.action(3,2); // 第二个参数表示缩放比例
sprite.runAction(action);
}

/**
* 图层(僵尸)旋转(1),达到一定角度,在例子中会走捷径(逆时针转90度)
*/
private void rotetaTo(){
CCRotateTo action = CCRotateTo.action(3,270);
sprite.setAnchorPoint(0.5f,0.5f);
sprite.runAction(action);
}

/**
* 图层(僵尸)旋转(2),偏移量,在例子走会转完(顺时针转270度)
*/
private void roteteBy(){
CCRotateBy action = CCRotateBy.action(3,270);
sprite.setAnchorPoint(0.5f,0.5f);
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(1)绝对,坐标
*/
private void moveTo(){
CCMoveTo action = CCMoveTo.action(3,ccp(200,0));
sprite.runAction(action);
}

/**
* 图层(僵尸)移动(2)相对,偏移量
*/
private void moveBy(){
CCMoveBy action = CCMoveBy.action(3,ccp(200,0));
sprite.runAction(action);
}
}

注意:这里如果不使用CCRepeatForever包装动画,会报出空指针异常:因为动画只提供了7帧,没有后面的帧数了。解决这个问题的另一个方法是让这个动画只执行一次,即在CCAnimate.action()的第二个参数写入一个false。

11.总结

Cocos2D调用顺序:视图(CCGLSurfaceView) ——> 导演(CCDirector) ——> 场景(CCScene) ——> 图层(CCLayer) ——> 精灵(CCSprite) ——> 动作(CCMove)