//屏幕适配方案
1,EXACT_FIT//完美填充强制拉伸或者压缩图片
2,NO_BODER //如果设计尺寸与屏幕尺寸不同,
//只是满足上下边或者左右边,实际中看屏幕的比例
3,SHOW_ALL//等比例放大,全部都显示出来,可能会出现黑边
//盖不完,尺寸的不匹配的坏处没有2严重
4,FIXED_HEIGHT//固定高度为设计高度(宽度等比例增大或者缩小)
//位置也会改变,向左侧对齐整
5,FIXED_WIDETH//宽度固定,高度不管
//(可能上下处会出现黑边(没有使用)),但是左右会全部显示
//不过图片的位置也会相应的改变(下对齐)
//游戏的第一个概念
场景(启动场景,游戏开始菜单)拍电影一样
切换场景
1,完善菜单场景
2,项目实现——创建一个菜单场景类
游戏的基本概念;
补充:
c/c++的宏:
#define bakeground "hgfd.png"//替换,方便维护程序
#define BLOOD_HURT 10
c/c++头文件:
#include "jhfkajb.h"
c/c++防止头文件重复包含
#ifndef _CONST_H_//->const.h(如果没有定义下面就马上定义)
#define _CONST_H_//防止头文件重复包含
#endif//结尾带上
c/c++命名空间:
namespace <名字>{
内容
}
//1,使用
<名字>::<功能>;
//2,使用
using namespace <名字>;
//下面就可以直接调用这里面的功能
c/c++类的基本使用
/**
妖兽(怪兽)
int
char
float
c语言的“结构体”,是程序员自定义的数据类型
*/
struct monster {
int age;
int grade;//级别 等级
char name[16];
};
int main(void){
struct monster m1;
m1.age=200;
m1.grade=3;
strcpy(m1.name,"buf");
}
c语言描述有限制,不能实现面向对象的编程
所以就可以用c++的类来实现上面的功能
?c语言是面向过程编程--->>>>
--->>>c++是面向对象编程--->>>>
面向过程编程:
面向对象编程:
主人:
买菜
菜商:
报价
卖菜
c++的类:(一种功能更强大的结构体)
妖兽 monster
数据 :
等级,grade
年龄,age
方法:
获取等级 getGrade
进级 upGrade
渡劫
(类是c++的特点)名称:class
class Monster{ (定义一个Monster的类)(建模)
public: (下面的方法都可以调用)(公开权限)(任何人都可以调用)
int getGrade();
int getAge();
void UpGrade();
void CrossDisaater();//渡劫
//普通成员函数(属于这一个妖兽)
//m1.Compare(m2);
int Compare(Monster other);
//静态成员函数(属于整个类,只要是这种类就可以直接调用)
//Monster::Compare(m1,m2);//调用
static int Compare(Monster other);
//构造函数(没有参数称为默认构造函数)
Monster(){
grade=1;
age=0;
}
//带参数的构造函数
Monster(int gradevalue,int agevalue)
{
grade=gradevalue;
age=agevalue;
}
//定义一些数据
private: //“私有的”
int grade;
int age;
};
//上面实现了方法的声明:下面是方法的实现:
int Monster::getGrade(){
return 0;
}
int Monster::getAge(){
return age;
}
int MUpGrade::UpGrade(){
grade++;
}
int MUpGrade::CrossDisaater(){
if(grade>10){
std::cout<<"渡劫成功"<<std::endl;
}else{
std::cout<<"渡劫失败,级别不够"<<std::endl;
}
}
int main()
{
//创建类
Monster m1;
Monster m2(5,200);
std::cout<<"m1的年龄是:"<<m1.getAge()<<std::endl;
std::cout<<"m1的级别是:"<<m1.getgrade()<<std::endl;
std::cout<<"m2的年龄是:"<<m2.getAge()<<std::endl;
std::cout<<"m2的级别是:"<<m2.getgrade()<<std::endl;
m1.Compare(m2);
return 0;
}
c/c++类的静态成员函数
class Monster{ (定义一个Monster的类)(建模)
public: (下面的方法都可以调用)(公开权限)(任何人都可以调用)
int getGrade();
int getAge();
void UpGrade();
void CrossDisaater();//渡劫
//普通成员函数(属于这一个妖兽(对象))
//m1.Compare(m2);
int Compare(Monster other);
//静态成员函数(属于整个类,只要是这种类就可以直接调用)
//Monster::Compare(m1,m2);//调用
static int Compare(Monster a,Monster b);
static int Compare(Monster& a,Monster& b);
//引用类型不会存在值传递(直接调用过来),不会进行值的拷贝->c++特性
//构造函数(没有参数称为默认构造函数)
Monster(){
grade=1;
age=0;
}
//带参数的构造函数
Monster(int gradevalue,int agevalue)
{
grade=gradevalue;
age=agevalue;
}
//定义一些数据
private: //“私有的”
int grade;
int age;
};
void Monster::Compare(Monster a,Monster b){
if(a.grade>b.grade){
std::cout<<"秒杀"<<std::endl;
}else if(a.grade<b.grade){
std::cout<<"被秒杀"<<std::endl;
}else {
std::cout<<"不相上下"<<std::endl;
}
}
c/c++类的继承
妖兽进化成妖仙(精灵)->有自己独有的特点
定义一个全新的类:里面包含妖兽的特性
//定义妖仙类Sprite
//以公有的方式来继承Monster
class Sprite:public Monster{
};
class Son:public Father{
public:
void playgame();
private:
std::string toy;
}
c/c++指针:
指针的定义
指针的初始化
值传递,赋值,改变值;
c/c++指向结构体的指针
struct monster *p;
p=m1;
p1->mame;p->age;p->grade;
(*p).name;(*p).age;
c/c++指向对象的指针
Monster *p;
p=&m1;
p->getAge();p->getgrade();
this->getAge;this->getgrade;
c/c++虚函数
指向父类的指针可以指向子类
但是调用父类子类同名的方法时候都是调用父类的方法
//使用虚函数
定义的时候
virtual void attack(void);//virtual关键字
Father *p;
p=&son;
protect(p);
13,游戏引擎基础--场景
Scence:场景
node:节点
transitionScence:特效场景(切换场景的特效)
注意:不要再场景中添加场景
场景的创建:Scence*Scence::create()
场景的运行:void runWithScence(Scence*Scence)
都是导演类Director的方法
通常在applicationDidFinishLaunching方法中调用 runWithScence
来运行第一个场景
注意: runWithScence是无过度效果的场景切换;
一般用于运行第一场景。
例如:
director-> runWithScence(Scence);
14, 游戏引擎基础--布景层
layer:布景层(图层)
1,图层的基本概念
图层:layer是node的子类
图层:相当于一个透明的容器
control UI控件 _layerRGBA ScrollView滚动视图控件
layerColor颜色图层 LayerMultiplex Menu菜单
锚点:确定钉子的位置
(0.5,0.5)中点;
(0,0)左下角://百分比值
auto layer=layer::creat();//创建一个图层
layer->ignoreAnchorPointForPosition(false);//忽略锚点对位置的影响
//使用该图层的锚点,此时使用默认锚点(中点,(0.5,0.5))
场景可以包含多个图层(布景层(layer))
每个图层可以包含不同的元素
多个图层可以实现叠加效果
2,layer的初始化
1)init:
初始化layer
creat方法中调用init
一般在init方法定义要显示的对象
一个layer只会调用一次init方法
2)onEter
进入布景层(图层)时调用onEter
即:把图层作为子节点添加到父节点时,调用该图层的onEter方法
即:场景->addChild(图层)
一个layer对象可能调用多次onEnter方法
3)onExit
离开图层时调用onExit
即:把图层从其父节点移除时,调用该图层的onExit方法
1,创建菜单场景类
CREATE_FUNC //宏替换
例如:
#define ADD_ONE(a) a+1
int main()
{
int x;
x=ADD_ONE(100);
printf("x=%d\n",x);
return 0;
}
例二:
#difine max(type) \
type max(type a,type b){\
int ret;\
if(a>b)\
ret=a;\
else \
ret=b;\
return ret;\
}
使用:max(type);//返回值类型不确定
max(int)
int main()
{
int x;
x=max(100,200);
printf("%d",x);
return 0;
}
//CREATE_FUNC(MenueScence);
//创建一个MenueScence类型的对象
//new
//变量
//栈空间的变量
//函数内部定义变量,默认是栈空间
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
if (pRet && pRet->init()) \
{ \
//autorelease();把pRet指向的对象,放到自动释放池中
//当不使用的时候就把占用的堆空间释放
pRet->autorelease(); \
//在栈空间分配空间储存变量
//在堆空间创建一个对象,一直都存在,放在堆空间不会消失
return pRet; \
} \
else \
{ \
delete pRet; \//c++用来释放堆空间的内存的
pRet = nullptr; \
return nullptr; \
} \
}
2,添加背景
1,精灵Sprite
sprite
用来表示,图片,人物,背景
能够执行动画,动作
主要方法:
Sprite* Sprite ::creat(const std::string& filename)
实例:
//Sprite*testSprite=Sprite ::creat("MonKey.png");
auto hero =Sprite::create("Monkey.png");
2,坐标系
1,钉子的位置:
锚点:对于“精灵”默认在这个精灵的中心位置
2,父节点的位置
4,项目实现 添加标题
添加一个标题上下摆动
1,动作
动作的基类是Action
Action为所有的动作提供了公有的方法;
reverse()表示动作的逆向执行。
isDone()动作是否执行结束
stop()停止动作
2,MoveBy
相对于当前位置,把精灵移动一段距离。
auto move =MoveBy::create(1.0f,Vec2(100,100));//1.0f--浮点数-时间
//第二个参数表示位置(在x方向前进100个像素,在y方向前进100个像素==向右上角移动)
//创建了这个动作就得让精灵(它的方法)来执行这个动作
Sprite->runAction(move);
3,顺序执行动作Sequence
按照指定顺序先后执行一系列动作。
顺序动作中如果包含RepeatForever,将可能导致错误
(因为顺序动作,是等前一个动作执行完成后才开始执行下一个动作,
而RepeatForever是永远不会执行结束的)
auto move1=Move::create(1,Vec2(100,100));//参数1表示动作执行时间为一秒
auto move2=Move::create(1,Vec2(-100,-100));
auto action = Sequence::create(move1,move2,NULL);
Sprite->runAction(action);
4,重复执行动作
让某个精灵重复执行某一个动作,指定重复次数
auto move1=Move::create(1,Vec2(100,100));//参数1表示动作执行时间为一秒
auto move2=Move::create(1,Vec2(-100,-100));
auto seq = Sequence::create(move1,move2,NULL);
auto repeat = Repeat::create(seq,6);
Sprite->runAction(repeat);
5,永久重复动作RepeatForever
auto move1=Move::create(1,Vec2(100,100));//参数1表示动作执行时间为一秒
auto move2=Move::create(1,Vec2(-100,-100));
auto seq = Sequence::create(move1,move2,NULL);
auto repeat = RepeatForever::create(seq);
Sprite->runAction(repeat);
2,项目精讲
按钮:BUTTON
头文件:
#include"ui/CocosGUI.h"
域名
using namespace ui;
常用接口
auto btn = Button::create("1.png","2,png");
//创建按钮上的标题
button ->setTitleText("NEW GAME");
startButton->loadTextureNormal("1.png");
startButton->loadeTexturePressed("1.png");
//添加事件处理函数
addTouchEventListener
2,创建游戏项目
GameScence.h;
创建方式和创建菜单场景是一样的
//#pragma once//保证该头文件只会被包含一次->只有vs支持
#include "cocos2d.h"
//c/c++通用方法---->>>宏
#ifndef _GAMESCENCE_H_
#define _GAMESCENCE_H_
using namespace cocos2d;
//也可以写为->USING_NS_CC;
#include"ui/CocosGUI.h"
using namespace ui;
class GameScence : public Layer {
public:
static Scene* createScene();
virtual bool init();
//宏
//方便生成一个特定版本的create函数
CREATE_FUNC(GameScence);
//按钮处理函数
void touchEvent(Ref*sender, Widget::TouchEventType type);
};
#endif
3,场景的跳转
方式一:
Director::getinstanse()->runWithScence(scene);
无过度效果的场景切换
一般用于运行第一场景。
方式二
void pushScene(Scene* scene)
把场景压入栈,并显示该场景,原场景依然在栈中。
方式三:
void popScene()
弹出栈顶的场景
原场景称为新的栈顶场景,并显示原来的场景
常和pushScene成对出现
方式四:
void popToRootScene()
弹出栈中除了根场景之外的所有场景
方式五:
void replaceScene(Scene* scene)
用一个新的场景替换旧的场景,也就是场景的切换,
但是旧的场景不再保留,节省内存;
2)特效场景(TranSitionScence)
*********************case语句不可以定义变量********
********************但是可以加一个作用域***********
case Widget::TouchEventType::ENDED:
{
auto destScene = GameScence::createScene();
Director::getInstance()->pushScene(destScene);
break;
}
3.实现主角飞行(一)
主角持续向右飞行。
实现方案:让背景持续水平滚动,主角不动,产生主角持续飞行的视觉效果
1)远景背景,以最慢的速度向左滚动,设计一个左右侧可以衔接的图片
使用同一个图片,创建两个水平拼接的精灵,利用事件循环,实现循环左移
2)近景背景,以比较快的速度向左滚动和远景背景相似
3)主角背景,以最快的速度向左滚动,因为
有很多无规则位置的障碍物和礼物,而且图片很长,使用瓦片地图实现
各种背景资源图片
极远背景bj1.jpg 不动的
较远背景(半透明)bj2.png 较快
稍微远的背景(半透明)bj3.png 非常快
项目精讲:
1,游戏元素的层级关系
游戏中元素的层级关系由z-order属性来决定。
我们可以通过设置元素的z-order值来控制元素之间的渲染顺序。
默认情况下,所有的元素的z-order为0,
所以当游戏元素没有设定z-order值时,游戏中的元素将按照添加顺序来显示。
所以,我们在添加游戏背景或其它元素时,应该要注意下他们的添加顺序或z-order值,
不要出现遮挡的现象
2,Vector容器
2.1:c++的Vector容器
在c++中,Vector是一个十分有用的容器。
表示可变大小数组的序列容器
Vector是一个能够存放任意类型的动态数组,能够增加和删除数据
非常适合表示长度变化,而且插入和删除操作仅限于最后一个元素的“数组”
不适合表示长度特别大的数组(开销较大),因为Vector是连续储存的。
demo
#include<iostream>
#include<vector>
#include<stdio.h>
using namespase std;
//让用户输入任意多个整数,保存到vector中
//直到用户输入一个浮点数
int main()
{
int x;
int ret;
vector<int> data;
cout<<"size: "<<data.size()<<endl;//个数
cout<<"Capacity: "<<data.capacity()<<endl;//容量(每次稍微多一点方便下次添加)
while(1)
{
cout<<"请输入一个整数";
ret = scanf("%d",&x);
if(ret<=0)break;
}
data.push_back(x);//把x添加到尾部
cout<<"size: "<<data.size()<<endl;
cout<<"Capacity: "<<data.capacity()<<endl;
//遍历
for(int i=0;i<datd.size();i++)
cout<<datd[i]<<" ";
//删除最后一个元素
//data.pop_back();
return 0;
}
//指针 引用
//遍历,使用迭代器(就是一种特殊的指针)
void show3(vector<int> &data)
{
for(auto it=data.begin();it!=data.end();it++)
cout<<*it<<" ";
cout<<endl;
}
2.2 cocos2d-x的vector容器
在c++的vector基础上进行了封装,使用方便。
3.时间的调度
游戏的帧循环。
ScheduleTest.h
//以上课堂为腾讯课堂-----零基础开发大型游戏