例如:愤怒的小鸟
游戏的实现原理:在不同时间片段中绘制不同画面
代码片段
// 绘制画面
drawMenu(); // 绘制游戏主菜单画面
drawGame(); // 绘制游戏中画面
drawOver(); // 绘制游戏结束画面
// 不同状态渲染不同画面
draw(){
while(isExit){
if(isState==MENU){
drawMenu();
}else if(isState==GAME){
drawGame();
}else if(isState==OVER){
drawOver();
}
}
}
// 游戏事件处理函数
event(){
isState==MENU;
}
游戏归根到底是绘制渲染
渲染驱动游戏重要指标,帧率(FPS, Frame Per Second)。
例如:象棋游戏或者是棋牌类游戏
drawMenu();
drawGame();
drawOver();
// 事件处理函数
event(){
if(isState==MENU){
drawMenu();
}else if(isState==GAME){
drawGame();
}else if(isState==OVER){
drawOver();
}
}
游戏开发技术平台差异
跨平台游戏开发技术方案
Cocos2D-X跨平台解决方案
Cocos2D-X 版本选择
根据图形标准划分
Cocos2D-X功能模块
Cocos2D-X数据结构
软件需求
$ python -V
Python 2.7.13
Win10安装VS2015
win32环境搭建
实例软件:Cocos2d-x 3.10 Lua
-- 下载安装并更新
$ git clone https://github.com/cocos2d/cocos2d-x.git
$ cd cocos2d-x && python download-deps.py
$ git submodule update --init
-- 创建项目
$ ./setup.py
$ source FILE_TO_SAVE_SYSTEM_VARIABLE
$ cocos new ProjectName -p com.company.game -l lua -d NEW_PROJECTS_DIR
$ cd NEW_PROJECTS_DIR/ProjectName
应用程序生命周期
一个游戏对应一个Application
对象,Application
职责是管理游戏生命周期并设置默认游戏窗口,获取平台及本地化信息。Cocos2D-X通常不直接创建Application
对象,Cocos2d-x脚本创建应用程序时会实现一个Application
的子类供程序员自行定义生命周期的各个阶段的处理,这个子类即AppDelegate
。
#ifndef _APP_DELEGATE_H_
#define _APP_DELEGATE_H_
#include "cocos2d.h"
/**AppDelegate是一个应用程序委托对象,作用是程序启动时调用它。*/
class AppDelegate : private cocos2d::Application
{
public:
AppDelegate();
virtual ~AppDelegate();
virtual void initGLContextAttrs();
/**
游戏启动后触发,一般进行游戏初始化。
*/
virtual bool applicationDidFinishLaunching();
/**
游戏退出到后台
*/
virtual void applicationDidEnterBackground();
/**
游戏从后台进入前台
*/
virtual void applicationWillEnterForeground();
};
#endif
设计思想
导演
场景
图层
Layer
图层是处理玩家事件响应的Node
子类,包含的是直接在屏幕上呈现的内容, 它实现了触屏事件代理协议(TouchEventsDelegate
)。
Layer
图层的作用
Layer
类主要函数
init()
初始化图层onEnter()
进入布景层时被调用onExit()
离开布景层被调用onEnterTransitionDidFinish()
过程动画结束时调用节点
每个节点中都有一个摄像机
显示对象
-- 预加载图片
local img = cc.Director:getInstance():getTextureCache():addImage("logo.jpg")
-- 获取文件尺寸
local size = img:getContentSize()
print(size.width, size.height)
-- 创建精灵并添加至当前场景中
display.newSprite(img):addTo(self):move(display.center)
-- 创建图层
local layer = display.newLayer():addTo(self):move(100, 100)
local image = display.newSprite("head/head_1.png"):addTo(layer)
image:setAnchorPoint(cc.p(0, 0))
示例:显示隐藏节点
-- MainScene.lua
local MainScene = class("MainScene", cc.load("mvc").ViewBase)
function MainScene:onCreate()
-- 场景中添加背景图
local bg = display.newSprite("bg.jpg"):move(display.center):addTo(self)
-- 3秒后场景切换
self:getScheduler():scheduleScriptFunc(function()
local newScene = require("app.views.GameScene"):new()
cc.Director:getInstance():replaceScene(newScene)
end, 3, false)
end
return MainScene
-- GameScene.lua
local GameScene = class("GameScene", function()
return display.newScene("GameScene")
end)
function GameScene:ctor()
local logoNode = require("app.views.LogoNode"):new():addTo(self):move(display.center)
end
return GameScene
-- LogoNode.lua
local LogoNode = class("LogoNode", cc.load("mvc").ViewBase)
function LogoNode:ctor()
local logo1 = display.newSprite("logo1.png"):addTo(self)
local logo2 = display.newSprite("logo2.png"):addTo(self)
logo2:setVisible(false)
-- invalid 'cobj' in function 'lua_cocos2dx_Node_isVisible'
-- lua保存的node值相当于一个弱引用
-- 在创建 Node节点后 调用父节点 retain() 方法 手动增加引用
logo1:retain()
logo2:retain()
-- print(not logo1:isVisible(), not logo2:isVisible())
self:getScheduler():scheduleScriptFunc(function()
-- invalid 'cobj' in function 'lua_cocos2dx_Node_isVisible'
logo1:setVisible(not logo1:isVisible());
logo2:setVisible(not logo2:isVisible());
end, 1, false)
end
return LogoNode
Action的基本使用
-- MainScene.lua
local MainScene = class("MainScene", cc.load("mvc").ViewBase)
function MainScene:onCreate()
local img = display.newSprite("role.png"):addTo(self)
img:move(display.center)
img:setScale(1)
img:setPositionX(100)
-- 2秒,从左到右移动到
-- img:runAction(cc.MoveTo:create(2, cc.p(display.width-100, display.cy)))
-- 2秒,从左向右移动300像素
-- img:runAction(cc.MoveBy:create(2, cc.p(-300, 0)))
-- 执行顺序序列
-- local fn1 = cc.MoveTo:create(2, cc.p(display.width-100, display.cy))
-- local fn2 = cc.MoveBy:create(2, cc.p(-300, 0))
-- img:runAction(cc.Sequence:create(fn1, fn2))
-- 来回移动
-- local fn1 = cc.MoveBy:create(2, cc.p(300, 0))
-- error in function 'lua_cocos2dx_Action_reverse' argument #1 is '[no object]'; 'cc.Action' expected.
-- local fn2 = fn1.reverse() --反转
-- img:runAction(cc.Sequence:create(fn1, fn2))
-- 并列执行
-- local fn1 = cc.MoveBy:create(2, cc.p(400, 0))
-- local fn2 = cc.ScaleTo:create(2, 2)
-- img:runAction(cc.Spawn:create(fn1, fn2))
-- 动画播放完的回调
local fn1 = cc.MoveBy:create(2, cc.p(400, 0))
local fn2 = cc.ScaleTo:create(2, 2)
local fn3 = cc.Spawn:create(fn1, fn2)
img:runAction(cc.Sequence:create(fn3, cc.CallFunc:create(function()
print("play complete")
end)))
end
return MainScene
Action特效
-- MainScene.lua
local MainScene = class("MainScene", cc.load("mvc").ViewBase)
function MainScene:onCreate()
local nodeGrid = cc.NodeGrid:create()
nodeGrid:addChild(display.newSprite("role.png"))
nodeGrid:move(display.center)
nodeGrid:setScale(1, 1)
nodeGrid:addTo(self)
-- 震动效果
-- nodeGrid:runAction(cc.Shaky3D:create(10, cc.size(50, 50), 5, false))
-- 瓦片式抖动
-- nodeGrid:runAction(cc.ShakyTiles3D:create(10, cc.size(50, 50), 5, false))
-- 爆炸碎片效果
-- nodeGrid:runAction(cc.ShuffleTiles:create(1, cc.size(50, 50), 5))
-- 碎片消失
-- nodeGrid:runAction(cc.TurnOffTiles:create(1, cc.size(100, 100)))
-- 波浪效果
-- nodeGrid:runAction(cc.Waves3D:create(2, cc.size(15, 10), 5, 40))
-- 波浪效果后回到初始状态
local waveRun = cc.Waves3D:create(2, cc.size(15, 10), 5, 40)
local waveInit = cc.Waves3D:create(2, cc.size(15, 10), 0, 0)
nodeGrid:runAction(cc.Sequence:create(waveRun, waveInit))
-- 先抖动后爆炸
-- local shaky = cc.ShakyTiles3D:create(1, cc.size(50, 50), 5, false)
-- local shuffle = cc.ShuffleTiles:create(0.5, cc.size(50, 50), 25)
-- nodeGrid:runAction(cc.Sequence:create(shaky, shuffle))
end
return MainScene