Cocos2d-x 3.0final 终结者系列教程16-《微信飞机大战》实现
看到cocos2d-x推出了3.1版本号,真是每月一次新版本号,速度。
另一个好消息就是http://cn.cocos2d-x.org/上线了,祝贺!啥时候把我的视频和教程放上去呢?!!
。
视频下载地址:http://pan.baidu.com/s/1jGiLOG2
本文介绍一款纵版射击游戏的实现,开发环境:
win7
vs2012
cocos2d-x3.0final
android adt
android ndk r9
首先看下最后的效果:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2Roam9i/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
(图1。微信飞机大战执行效果)
源代码下载地址:http://download.csdn.net/detail/sdhjob/7513863
一、游戏资源准备
menu.png 首页的菜单背景 |
|
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2Roam9i/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""> |
about.png 关于界面 |
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2Roam9i/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""> |
help.png 帮助界面 |
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2Roam9i/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""> |
background3.png 游戏场景的 |
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2Roam9i/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt=""> |
end.png |
bullet.png aaa.png
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2Roam9i/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">ccc.png |
子弹和敌机文件 |
爆炸效果 (被CSDN的博客加上水印。就这样了,大家还是下源代码吧) |
二、Cocos2d-x3.0项目创建和VS2012编译
2.1进入命令提示符输入:
cocos new -p com.xdl.game -d c:/users/administrator/desktop/game2014 -l cpp planegame
2.2 然后进入桌面/game2014/planegame/proj.win32
2.3使用vs2012打开
planegame.sln
2.4 按F5编译执行项目,将会出现HelloWorld的界面
2.5.把全部的资源复制到 桌面/game2014/planegame/Resources文件夹下(处理图片还有3个声音文件)
三、场景跳转和主菜单实现
3.1.改动HelloWorldScene,在init方法中加入3个菜单栏目:
auto gameItem=MenuItemFont::create("StartGame",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
auto helpItem=MenuItemFont::create("Help",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
auto aboutItem=MenuItemFont::create("About",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
gameItem->setPosition(Point(origin.x + visibleSize.width/2 - closeItem->getContentSize().width/2,200 ));
helpItem->setPosition(Point(origin.x + visibleSize.width/2 - closeItem->getContentSize().width/2,150 ));
aboutItem->setPosition(Point(origin.x + visibleSize.width/2 - closeItem->getContentSize().width/2,100 ));
gameItem->setColor(Color3B::BLACK);
helpItem->setColor(Color3B::BLACK);
aboutItem->setColor(Color3B::BLACK);
gameItem->setTag(11);
helpItem->setTag(12);
aboutItem->setTag(13);
3.2 改动菜单的回调方法MenuCallBack
void HelloWorld::menuCloseCallback(Ref* pSender)
{ MenuItem * nowItem=(MenuItem *)pSender;
SimpleAudioEngine::getInstance()->playEffect("select.wav"); //播放音乐
switch(nowItem->getTag())
{
case 10:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
break;
case11://game
Director::getInstance()->replaceScene(GameScene::createScene());
break;
case12://help
Director::getInstance()->replaceScene( TransitionFlipY::create(1,HelpScene::createScene()));
break;
case13://about
Director::getInstance()->replaceScene( TransitionFlipY::create(1,AboutScene::createScene()));
break;
}
}
这样通过导演对象实现场景跳转。
3.3 在帮助。关于场景实现跳转回来
须要在项目中加入3个.h文件和3个.cpp文件,保存到Classes文件夹下(注意文件夹,不要保存错了)
HelpScene.h
HelpScene.cpp
GameScene.h
GameScene.cpp
AboutScene.h
AboutScene.cpp
若想在帮助和关于场景跳转回来须要增加触摸消息处理,见HelpScene的init方法:
bool HelpScene::init(){
if(!Layer::init())
{
return
false;
}
auto spbk=Sprite::create("help.png");
spbk->setPosition(Point::ZERO);
spbk->setAnchorPoint(Point::ZERO);
this->addChild(spbk);
EventListenerTouchOneByOne * touch=EventListenerTouchOneByOne::create();
touch->onTouchBegan=[](Touch * touch,Event * event){
return true;
};
touch->onTouchMoved=[](Touch * touch,Event * event){
Director::getInstance()->replaceScene( HelloWorld::createScene());
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(touch,this);
return true;
}
四、游戏场景背景滚动
4.1首先在GameScene的init方法加入背景层,代码例如以下:
auto spbk=Sprite::create("background4.png");
spbk->setAnchorPoint(Point::ZERO);
spbk->setPosition(Point::ZERO);
this->addChild(spbk);
spbk->setTag(10);
auto spbk02=Sprite::create("background4.png");
spbk02->setAnchorPoint(Point::ZERO);
spbk02->setPosition(Point::ZERO);
spbk02->setPositionY(spbk->getPositionY()+680);
this->addChild(spbk02);
spbk02->setTag(11);
为什么要加入2遍呢?由于要实现循环的贴图效果,
4.2 在init方法计划任务
this->schedule(schedule_selector(GameScene::moveBackground),0.01);
4.3 处理计划任务
void GameScene::moveBackground(float t)
{
auto spbk=this->getChildByTag(10);
auto spbk02=this->getChildByTag(11);
spbk->setPositionY(spbk->getPositionY()-1);
if(spbk->getPositionY()<-680)
{
spbk->setPositionY(0);
}
spbk02->setPositionY(spbk->getPositionY()+680);
}
这样就形成了循环贴图的效果,游戏游戏是横版的,还有将这样的循环贴图通过多层实现场景纵深效果(近处图层移动快,远处移动慢)
当背景相对屏幕向下移动,飞机相对屏幕不懂,但飞机相对背景则向上飞行(好多游戏的主角事实上一直在屏幕中间)
五、飞机动画和触摸控制
5.1 在init方法创建飞机动画
auto spPlane=Sprite::create();
spPlane->setTag(110);
spPlane->setPosition(Point(160,240));
this->addChild(spPlane);
Vector<SpriteFrame*> allframe;//保存动画的每一帧
for(int i=0;i<4;i++)
{
SpriteFrame * sf=SpriteFrame::create("player.png",Rect(i*47,0,47,56));
allframe.pushBack(sf);
}
Animation * ani=Animation::createWithSpriteFrames(allframe,0.1);
spPlane->runAction(RepeatForever::create(Animate::create(ani)));
5.2 通过触摸控制飞机移动
EventListenerTouchOneByOne * event=EventListenerTouchOneByOne::create();
event->setSwallowTouches(true);
event->onTouchBegan=CC_CALLBACK_2(GameScene::onTouchBegan,this);
event->onTouchMoved=CC_CALLBACK_2(GameScene::onTouchMoved,this);
event->onTouchEnded=CC_CALLBACK_2(GameScene::onTouchEnded,this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(event,this);
-------在GameScene中加入下面方法
bool GameScene::onTouchBegan(Touch *touch, Event *unused_event){
px=touch->getLocation().x;
py=touch->getLocation().y;
return true;
}
void GameScene::onTouchMoved(Touch *touch, Event *unused_event){
int mx=(touch->getLocation().x-px);
int my=(touch->getLocation().y-py);
auto spPlane=this->getChildByTag(110);
spPlane->runAction(MoveBy::create(0,Point(mx,my)));
px=touch->getLocation().x;
py=touch->getLocation().y;
}
void GameScene::onTouchEnded(Touch *touch, Event *unused_event){
}
这样就实现了在屏幕滑动改变飞机坐标。
六、子弹发射
6.1 在GameScene中加入成员Vector用来保存全部的子弹层
Vector<Sprite *> allBullet;
6.2 计划任务,定时产生子弹和移动子弹
this->schedule(schedule_selector(GameScene::newBullet),0.5);
this->schedule(schedule_selector(GameScene::moveBullet),0.01
6.3 实现产生子弹的方法和移动子弹的方法
void GameScene::newBullet(float t){
auto spPlane=this->getChildByTag(110);
Sprite * bullet=Sprite::create("bullet3.png");
bullet->setPosition(spPlane->getPosition());
this->addChild(bullet);
this->allBullet.pushBack(bullet);
}
void GameScene::moveBullet(float t){
for(int i=0;i<allBullet.size();i++)
{ auto nowbullet=allBullet.at(i);
nowbullet->setPositionY(nowbullet->getPositionY()+3);
if(nowbullet->getPositionY()>Director::getInstance()->getWinSize().height)
{
nowbullet->removeFromParent();
allBullet.eraseObject(nowbullet);
i--;
}
}
}
七、敌机实现
敌机实现与子弹实现类似,仅仅只是一个是向上飞,一个是向下飞。
7.1 在GameScene中加入成员Vector用来保存全部的子弹层
Vector<Sprite *> allEnemy;
7.2 加入产生敌机的任务
this->schedule(schedule_selector(GameScene::newEnemy),0.5);
this->schedule(schedule_selector(GameScene::moveEnemy),0.01)
7.3 实现敌机任务方法,这里产生2种不同类型的敌机
void GameScene::newEnemy(float t){
Sprite * enemy=nullptr;
int num=rand()%10;//随机数0-9
if(num>=3)
{
enemy=Sprite::create("aaa.png");
enemy->setTag(1000);
}
else
{ enemy=Sprite::create("ccc.png");
enemy->setTag(2000);
}
enemy->setPosition(Point(rand()%300+10,500));
this->addChild(enemy);
this->allEnemy.pushBack(enemy);
}
void GameScene::moveEnemy(float t){
for(int i=0;i<allEnemy.size();i++)
{ auto nowenemy=allEnemy.at(i);
nowenemy->setPositionY(nowenemy->getPositionY()-3);
if(nowenemy->getPositionY()<0)
{
nowenemy->removeFromParent();
allEnemy.eraseObject(nowenemy);
i--;
}
}
}
八、碰撞检測和加分
8.1 加入和引擎主线程fps一致的任务处理方法update
this->scheduleUpdate();
8.2 实现碰撞检測游戏逻辑
void GameScene::update(float t){
auto spPlane=this->getChildByTag(110);
Rect rp(spPlane->getPositionX(),spPlane->getPositionY(),47,56);
for(int i=0;i<allEnemy.size();i++)
{ auto nowenemy=allEnemy.at(i);
Rect er(nowenemy->getPositionX(),nowenemy->getPositionY(),40,50);
if(rp.intersectsRect(er))
{ //爆炸
newBomb(spPlane->getPositionX(),spPlane->getPositionY());
//移除敌机
nowenemy->removeFromParent();
allEnemy.eraseObject(nowenemy);
i--;
//播放音乐
SimpleAudioEngine::getInstance()->playEffect("explo.wav");
//停止全部任务和动作
//Director::getInstance()->getActionManager()->pauseAllRunningActions();
this->pauseSchedulerAndActions();
auto spover=Sprite::create("end.png");
spover->setPosition(Point::ZERO);
spover->setAnchorPoint(Point::ZERO);
this->addChild(spover);
auto act=Sequence::create(
DelayTime::create(2), //等待2秒
CallFunc::create(this,callfunc_selector(GameScene::jumpToMenu)),//运行跳转方法
NULL
);
this->runAction(act);
}
//敌机和子弹碰撞检測
for(int j=0;j<allBullet.size();j++)
{ auto nowbullet=allBullet.at(j);
Rect br(nowbullet->getPositionX(),nowbullet->getPositionY(),20,20);
if(er.intersectsRect(br))
{//改动分数
Label * labScore=(Label*)this->getChildByTag(120);
score+=nowenemy->getTag();
//爆炸效果
newBomb(nowbullet->getPositionX(),nowbullet->getPositionY());
//粒子效果
auto ps=ParticleSystemQuad::create("bomb.plist");
ps->setPosition(Point(nowbullet->getPositionX(),nowbullet->getPositionY()));
this->addChild(ps);
labScore->setString(String::createWithFormat("score:%d",score)->_string);
//移除子弹层
nowbullet->removeFromParent();
allBullet.eraseObject(nowbullet);
//移除敌机层
nowenemy->removeFromParent();
allEnemy.eraseObject(nowenemy);
i--;
//音效
SimpleAudioEngine::getInstance()->playEffect("explo.wav");
break;
}
}
}
}
九、爆炸效果
当碰撞检測到,在飞机位置产生一个新的爆炸效果层,播放动画。动画播放完毕自己主动删除自己。
void GameScene::newBomb(int x,int y)
{
Vector<SpriteFrame*> allframe;
for(int i=0;i<7;i++)
{
SpriteFrame * sf=SpriteFrame::create("boom.png",Rect(i*44,0,44,47));
allframe.pushBack(sf);
}
Animation * ani=Animation::createWithSpriteFrames(allframe,0.03);
auto sprite=Sprite::create();
Action * act=Sequence::create(
Animate::create(ani), //动画
CCCallFuncN::create(sprite,callfuncN_selector(GameScene::killMe)),//调用自删除方法
NULL);
this->addChild(sprite);
sprite->setPosition(Point(x,y));
sprite->runAction(act);
}
void GameScene::killMe(Node * pSender)//自删除 pSender就是sprite这里是CallFunN,会传递节点过来
{
pSender->removeFromParentAndCleanup(true);
}
十、粒子特效和音乐播放
10.1 首先使用粒子编辑器编辑粒子文件bomb.plist(详见源代码)
10.2 加载粒子层
auto ps=ParticleSystemQuad::create("bomb.plist");
ps->setPosition(Point(nowbullet->getPositionX(),nowbullet->getPositionY()));
this->addChild(ps);
(假设粒子层也须要自删除。能够參考爆炸效果)
10.3 播放音乐和音效
首先要引入声音处理头文件和命名空间
#include "SimpleAudioEngine.h"
using namespace CocosDenshion;
然后就能够使用1条语句来播放音乐和音效了
SimpleAudioEngine::getInstance()->playBackgroundMusic("game.mp3",true); //播放背景音乐
SimpleAudioEngine::getInstance()->playEffect("explo.wav"); //播放音效
十一、判定死亡
在Update方法中,眼下仅仅增加了当敌机和飞机碰撞则死亡,实际游戏中可能有多有条件
如:敌机子弹和飞机碰撞、时间计数等,
void GameScene::update(float t){
auto spPlane=this->getChildByTag(110);
Rect rp(spPlane->getPositionX(),spPlane->getPositionY(),47,56);
for(int i=0;i<allEnemy.size();i++)
{ auto nowenemy=allEnemy.at(i);
Rect er(nowenemy->getPositionX(),nowenemy->getPositionY(),40,50);
if(rp.intersectsRect(er))
{ //爆炸
newBomb(spPlane->getPositionX(),spPlane->getPositionY());
//移除敌机
nowenemy->removeFromParent();
allEnemy.eraseObject(nowenemy);
i--;
//播放音乐
SimpleAudioEngine::getInstance()->playEffect("explo.wav");
//停止全部任务和动作
//Director::getInstance()->getActionManager()->pauseAllRunningActions();
this->pauseSchedulerAndActions();
auto spover=Sprite::create("end.png");
spover->setPosition(Point::ZERO);
spover->setAnchorPoint(Point::ZERO);
this->addChild(spover);
auto act=Sequence::create(
DelayTime::create(2), //等待2秒
CallFunc::create(this,callfunc_selector(GameScene::jumpToMenu)),//运行跳转方法
NULL
);
this->runAction(act);
}
。。。
void GameScene::jumpToMenu()//ï◊™µΩ÷˜≤Àµ•
{
SimpleAudioEngine::getInstance()->stopBackgroundMusic();
Director::getInstance()->replaceScene(HelloWorld::createScene());
}
十二、移植到Android平台
12.1 eclipse导入项目
在VS2012中开发好项目之后,使用adt工具(ecplise)导入项目,import
桌面\game2014\plangame\proj.android
12.2 改动jni/android.mk文件
加入编译的文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cocos2dcpp_shared
LOCAL_MODULE_FILENAME := libcocos2dcpp
LOCAL_SRC_FILES := hellocpp/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/GameScene.cpp \
../../Classes/HelpScene.cpp \
../../Classes/HelloWorldScene.cpp \
../../Classes/AboutScene.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module,2d)
$(call import-module,audio/android)
$(call import-module,Box2D)
12.3 进入cmd命令提示符
进入项目文件夹
cd c:/Users/Administrator/Desktop/game2014/planegame
编译当前项目
cocos compile -p android
(等吧。
。。最后会在c:/Users/Administrator/Desktop/game2014/planegame/proj.android/libs/armsabi/生成一个.so文件。 成功了!
)
12.4 拷贝Cocos2d-x android库文件
到 c:/Users/Administrator/Desktop/game2014/planegame/cocos/2d/platform/android/java/src/ 拷贝org目录到
c:/Users/Administrator/Desktop/game2014/planegame/proj.android/src 文件夹
在adt中刷新项目(这时候项目的错误会消除)
12.5 打包项目
使用手机数据线连接电脑,开启调试模式
能够直接通过run,来把该项目安装到手机。
之后使用android打包向导打包生成apk。
大功告成,大家最好还是投入半天时间做个《微信飞机大战》。下节课讲《2048》的开发。
Cocos2d-x 3.0final 终结者系列教程16-《微信飞机大战》实现的更多相关文章
- Cocos2d-x 3.0final 终结者系列教程13-贪食蛇游戏案例(全)
快过节了.谢谢了屈原,我们爱你. 应该多几个向屈大人一样跳江的,这样我们就能够放假纪念啦. ---------------------------------快过节了.弄个案例,大家最好还是假期做做, ...
- Cocos2d-x 3.0final 终结者系列教程01-无论是从cocos2d-x2.x升级到版本cocos2d-x3.x
诡谲的江湖,易变. 花花世界,车来人往. 最终确定.安家,将Cocos2d-x3.0final相关技术精加工的版本.并推出了博客文章, 不为他人,只为自己. 学习交流QQ群:301954471 --- ...
- Cocos2d-x 3.0final 终结者系列教程04-引擎架构分析
从前,有一个跟我来Android学生,总是问我: 沉老师,为什么Android的形式被称为Activity,为什么要onCreate方法写setContentView(R.layout.main)? ...
- Cocos2d-x 3.0final 终结者系列教程12-Vector&map&value
北京时间昨天下午,温40度.中午12:16我来到了篮球场点.思维1分钟决定开站 转球: 我和另一个3队友半开始, 我手中的球的那一刻我突然火爆球不稳,突然问,淡淡的味道橡胶和烧烤的味道混合. 个腾空跳 ...
- Cocos2d-x 3.0final 终结者系列教程03-源代码文件夹说明
话说今天从霍营到回龙观,走到天鑫家园东路.我肋哥去,堵死我啦.7:30出门,9:10还没到回龙观. 北京这交通真是坑爹.回过头想想.怪自己走小路,有时候确实快.可有时候真堵. 堵了35分钟后果断掉头, ...
- Cocos2d-x 3.0final 终结者系列教程08-画图节点Node中的锚点和坐标系
图片问答,(仅仅要回答正确,锚点和坐标系就学会了) 1.下图一共同拥有几个填充为淡黄色的实心矩形? 选择:A,2个 B, 4个 C,1个 D,16个 答案.B.4个 2.下图的4个实心矩形排列在几行 ...
- Cocos2d-x 3.0final 终结者系列教程15-win7+vs2012+adt+ndk环境搭建(无Cygwin)
最终不用Cygwin 了.非常高兴 为什么要用Win7? 由于VS2012要求Win7以上系统才干安装! 为什么要用vs2012? 由于VS2012才支持C++11! 为什么要支持C++11? 由于C ...
- Cocos2d-x 3.0final 终结者系列教程02-开发环境的搭建
本文主要以Mac平台和XCode5为基本系统环境和C++编程工具来介绍Cocos2d-x3.0final版的安装. 一.系统准备(预计要花掉半个月工资) MacBook Pro一台(本人的比較老.11 ...
- Cocos2d-x 3.0final 终结者系列教程05-AppDelegate入口类
下面是Cocos2d-x的程序入口: class AppDelegate : private cocos2d::Application { public: AppDelegate(); virtua ...
随机推荐
- Python 数据类型-3
字典 (dict) Python中唯一的映射的类型(哈希表) 字典对象是可变的,但是字典的键必须使用不可变的对象,一个字典可以使用不同类型的键值 定义字典: In [68]: dic = {} #使用 ...
- LeetCode OJ-- Divide Two Integers *
https://oj.leetcode.com/problems/divide-two-integers/ 在不使用乘法.除法.求余的情况下计算除法. 使用减法计算,看看减几次. 刚开始寻思朴素的暴力 ...
- HDU 1005 Number Sequence【斐波那契数列/循环节找规律/矩阵快速幂/求(A * f(n - 1) + B * f(n - 2)) mod 7】
Number Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- linux文本处理常用命令
linux文本处理常用命令 linux文本处理命令:grep.sed.printf.awk 1.grep grep的作用是按行查找字符,输出包含字符的行. #从文件查询 grep 'hello' ...
- 利用Django徒手写个静态页面生成工具
每个Geek对折腾自己的博客都有着一份执念 背景介绍 曾经多次在不同的平台写博客,但全部都以失败而告终.去年七月选择微信公众号做为平台开始了又一次的技术分享,庆幸一直坚持到现在,但随着文章发表的越来越 ...
- 使用aspnet_regsql.exe 创建ASPState数据库,用来保存session会话
使用aspnet_regsql.exe 创建ASPState数据库,用来保存session会话 因为公司有多台服务器,所以session要保存在sql server上,因此要在数据库中建立存放se ...
- 如何判断自己外网IP是否为真实公网IP,以及解决方案
如何判断本地(路由器)分配的IP是否公网IP? 公网IP:全球唯一IP地址.(公网IP又分为静态公网IP和动态公网IP,如何分辨的话,进入路由器查看连接方式pppoe连接都是动态公网IP.) ...
- 转: Linux下使用java -jar运行可执行jar包的正确方式
from: http://codepub.cn/2016/05/11/The-correct-way-to-use-java-jar-run-an-executable-jar-package-un ...
- mysql使用mysqldump 与 mysqlimport进行数据库迁移
1.导入数据库 1)source source /home/platvt/product/pc2_create_tables.sql 2)mysqlimport 使用mysqlimport导入数据: ...
- 【Python】切片
处理Python的部分元素,称之为切片. 创建切片 指定要是用的第一个元素和最后一个元素的索引,与range()函数一样,Python在到达你指定的第二个索引前面的元素后停止. 先定义一个列表vege ...