热门标签 | HotTags
当前位置:  开发笔记 > 程序员 > 正文

cocos2dx实例开发之2D横版跑酷

从网上下了一点素材资源,外加自己ps一点资源,然后东拼西凑写了一个横版跑酷的小游戏ps:csdn好不爽,无法传大点的gif,所以只好录了个短的gif,而且压缩之后凑合能看预览步骤1工程

从网上下了一点素材资源,外加自己ps一点资源,然后东拼西凑写了一个横版跑酷的小游戏

ps:csdn好不爽,无法传大点的gif,所以只好录了个短的gif,而且压缩之后凑合能看

预览

boyAnimation->addSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(str));
}

AnimationCache::getInstance()->addAnimation(boyAnimation,"boyAnimation");

//预加载帧动画
auto girlAnimation=Animation::create();
girlAnimation->setDelayPerUnit(0.2f);
for(int i=1;i<=8;i++)
girlAnimation->addSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("girl"+std::to_string(i)+".png"));
AnimationCache::getInstance()->addAnimation(girlAnimation,"girlAnimation");

////预加载音乐和音效
SimpleAudioEngine::getInstance()->preloadBackgroundMusic("spring_music.wav");
SimpleAudioEngine::getInstance()->preloadBackgroundMusic("winter_music.mp3");

SimpleAudioEngine::getInstance()->preloadEffect("jump.wav");
SimpleAudioEngine::getInstance()->preloadEffect("point.mp3");
SimpleAudioEngine::getInstance()->preloadEffect("gameover.wav");

//加载完毕跳转到游戏场景
auto mainMenu=MainMenu::createScene();
TransitionScene *transition=TransitionFade::create(1.0f,mainMenu);
Director::getInstance()->replaceScene(transition);
}

}

3 主菜单场景

添加一个菜单和对应的回调函数,分别有开始游戏、选项、关于等菜单项
//添加菜单
auto newGameItem=MenuItemImage::create("newgameA.png","newgameB.png",CC_CALLBACK_1(MainMenu::menuStartCallback,this));
newGameItem->setPosition(Point(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2));

auto optiOnItem=MenuItemImage::create("option_btn.png","option_btn.png",CC_CALLBACK_1(MainMenu::menuOptionCallback,this));
optionItem->setPosition(Point(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2-60));

auto aboutItem=MenuItemImage::create("aboutA.png","aboutB.png",CC_CALLBACK_1(MainMenu::menuAboutCallback,this));
aboutItem->setPosition(Point(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2-120));


auto menu=Menu::create(newGameItem,optionItem,aboutItem,NULL);
menu->setPosition(Point::ZERO);
this->addChild(menu,1);

4 游戏主场景

common头文件
这个头文件里面存储了一些定义的全局变量,比如关卡、男女角色选取等
//游戏关卡枚举
enum Level
{
SPRING,
WINTER
};


//游戏角色枚举
enum PlayerType
{
BOY,
GIRL
};

//游戏角色状态
enum PlayerState
{
RUN,
SLIDE,
JUMP
};

//地图元素枚举
enum BlockType
{
LAND, //砖块
NPC, //怪物
STAR, //星星
TOOL, //工具
NONE //空
};

//场景间隔基本单位定为80,分辨率800*480,则排满是10*6个格子,便于作碰撞检测
const float BLOCK_SIZE=80.0f;
const float PICKUP_SIZE=40.0f;
const float PLAYER_RADIUS=50.0f;
const float GRAVITY=-1500.0f;
const float PLAYER_SPEED=700.0f;
为了便于计算,将屏幕设计分辨率定位800*480,一个砖块或怪物的大小是80*80,一个拾取物的大小是40*40,这样计算坐标时只需要左整数倍数的偏移就可以了。
游戏里面设置了两种关卡,分别对应了春天和冬天的地图,春天的怪物是绿水灵,冬天的怪物是蓝蘑菇,(玩过冒险岛的都知道),同时还可以选择男、女两种角色。
都是用全局变量进行控制。


游戏角色player类
class Player:public Node
{
public:
virtual bool init() override;
CREATE_FUNC(Player);
public:
void run(); //主角奔跑
void jump(); //主角跳跃
void slide(); //主角滑行
PlayerState playerState; //角色状态
private:
Sprite *playerSprite; //奔跑的角色精灵
Sprite *playerSpriteSlideJump; //滑行和起跳的角色精灵
Animate *playerAnim;
Texture2D *jumpTexture;
Texture2D *slideTexture;

};
游戏角色分男女,具有奔跑、跳跃、滑行三种状态
角色还有奔跑动画,同时还要为角色绑定刚体,需要受物理引擎作用
playerSprite=Sprite::create(playerTextureName); //此处必须初始化一张角色纹理,否则后面无法切换纹理

jumpTexture=Sprite::create(playerJumpTexureName)->getTexture(); //创建跳跃纹理
slideTexture=Sprite::create(playerSlideTextureName)->getTexture(); //创建滑行纹理

playerAnim=Animate::create(playerAnimation);
this->addChild(playerSprite);

auto playerBody=PhysicsBody::createBox(playerSprite->getContentSize()); //这里要用包围盒,如果用圆形的话会导致滚动
playerBody->setDynamic(true);
playerBody->setContactTestBitmask(1);
playerBody->setGravityEnable(true);
playerBody->getShape(0)->setRestitution(0.0f); //设置刚体回弹力
this->setPhysicsBody(playerBody);

游戏移动地图类
主要是地图中的砖块和怪物等元素的无限滚屏移动
首先,在初始化里面,手动设置初始地图,放置砖块、怪物、拾取物等等
//手动搭建地图,没有加入即时计算~
//1层
for(int i=0;i<10;i++)
{
if(i!=3&&i!=4&&i!=7&&i!=8)
{
//添加land
auto block=Sprite::create(block_file);
block->setPosition(BLOCK_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+1*BLOCK_SIZE);
this->addChild(block);
block->setTag(LAND); //设置tag
auto blockBody=PhysicsBody::createBox(block->getContentSize());
blockBody->setDynamic(false);
blockBody->setContactTestBitmask(1);
blockBody->getShape(0)->setRestitution(0);
block->setPhysicsBody(blockBody);
}
}
//2层
for(int i=0;i<10;i++)
{
if(i==2||i==5||i==6)
{
//添加怪物
auto npc=Sprite::create(npc_file);
npc->setTag(NPC);
npc->setPosition(BLOCK_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+2*BLOCK_SIZE);
auto npcBody=PhysicsBody::createBox(npc->getContentSize());
npcBody->setDynamic(false);
npcBody->setContactTestBitmask(1);
npcBody->getShape(0)->setRestitution(0);
npc->setPhysicsBody(npcBody);
this->addChild(npc);
}
if(i==3)
{
//添加land
auto block=Sprite::create(block_file);
block->setPosition(BLOCK_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+1*BLOCK_SIZE);
this->addChild(block);
block->setTag(LAND); //设置tag
auto blockBody=PhysicsBody::createBox(block->getContentSize());
blockBody->setDynamic(false);
blockBody->setContactTestBitmask(1);
blockBody->getShape(0)->setRestitution(0);
block->setPhysicsBody(blockBody);
}
}
//3层
for(int i=0;i<10;i++)
{
if(i!=0&&i!=3&&i!=4)
{
//添加星星
auto star1=Sprite::create(star_file);
star1->setTag(STAR);
star1->setPosition(PICKUP_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+3*BLOCK_SIZE);
auto starBody1=PhysicsBody::createBox(star1->getContentSize());
starBody1->setDynamic(false);
starBody1->setContactTestBitmask(1);
starBody1->getShape(0)->setRestitution(0.0f);
star1->setPhysicsBody(starBody1);
this->addChild(star1);

auto star2=Sprite::create(star_file);
star2->setTag(STAR);
star2->setPosition(PICKUP_SIZE/2*3+i*BLOCK_SIZE,BLOCK_SIZE/2+3*BLOCK_SIZE);
auto starBody2=PhysicsBody::createBox(star2->getContentSize());
starBody2->setDynamic(false);
starBody2->setContactTestBitmask(1);
starBody2->getShape(0)->setRestitution(0.0f);
star2->setPhysicsBody(starBody2);
this->addChild(star2);

}

}
//4层
for(int i=0;i<10;i++)
{
if(i==3||i==4)
{
//添加land
auto block=Sprite::create(block_file);
block->setPosition(BLOCK_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+4*BLOCK_SIZE);
this->addChild(block);
block->setTag(LAND); //设置tag
auto blockBody=PhysicsBody::createBox(block->getContentSize());
blockBody->setDynamic(false);
blockBody->setContactTestBitmask(1);
blockBody->getShape(0)->setRestitution(0);
block->setPhysicsBody(blockBody);

}
if(i==8)
{
auto star1=Sprite::create(star_file);
star1->setTag(STAR);
star1->setPosition(PICKUP_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+3*BLOCK_SIZE);
auto starBody1=PhysicsBody::createBox(star1->getContentSize());
starBody1->setDynamic(false);
starBody1->setContactTestBitmask(1);
starBody1->getShape(0)->setRestitution(0.0f);
star1->setPhysicsBody(starBody1);
this->addChild(star1);

auto star2=Sprite::create(star_file);
star2->setTag(STAR);
star2->setPosition(PICKUP_SIZE/2*3+i*BLOCK_SIZE,BLOCK_SIZE/2+3*BLOCK_SIZE);
auto starBody2=PhysicsBody::createBox(star2->getContentSize());
starBody2->setDynamic(false);
starBody2->setContactTestBitmask(1);
starBody2->getShape(0)->setRestitution(0.0f);
star2->setPhysicsBody(starBody2);
this->addChild(star2);
}
if(i==6)
{
//添加道具
auto tool=Sprite::create(tool_file);
tool->setTag(TOOL);
tool->setPosition(PICKUP_SIZE/2+i*BLOCK_SIZE,BLOCK_SIZE/2+3*BLOCK_SIZE);
auto toolBody=PhysicsBody::createBox(tool->getContentSize());
toolBody->setDynamic(false);
toolBody->setContactTestBitmask(1);
toolBody->getShape(0)->setRestitution(0.0f);
tool->setPhysicsBody(toolBody);
this->addChild(tool);
}
}
每个物体都绑定了刚体,便于在物理世界做碰撞检测
然后需要启动无限滚屏
//启动调度器,地图滚屏
this->schedule(schedule_selector(GameMap::mapUpdate),0.01f);
目前所采用的策略是党某个node消失在左侧是,重新设置其坐标到有边缘从右往左移动,不过,更好的方法是动态的随机生成地图结点,但是算法较复杂。
void GameMap::mapUpdate(float dt)
{
for(auto &node:this->getChildren())
{
node->setPositionX(node->getPositionX()-3.0f);
if(node->getPositionX()<=-node->getContentSize().width/2)
node->setPositionX(node->getPositionX()+BLOCK_SIZE/2+10*BLOCK_SIZE);
}

}

游戏主场景类
这里有游戏最重要的逻辑代码。

一开始需要初始化物理引擎
auto *scene=Scene::createWithPhysics();
scene->getPhysicsWorld()->setGravity(Vec2(0,GRAVITY));

添加背景滚屏,这是底层背景,移动速度比地图移动速度慢,这样有层次感,有景深感觉,让画面更加动感
backGround1=Sprite::create(backGroundFile);
backGround1->setAnchorPoint(Point::ZERO);
backGround1->setPosition(Point::ZERO);
this->addChild(backGround1,0);
backGround2=Sprite::create(backGroundFile);
backGround2->setAnchorPoint(Point::ZERO);
backGround2->setPosition(Point::ZERO);
this->addChild(backGround2,0);
void GameScene::backGroundUpdate(float dt){	backGround1->setPositionX(backGround1->getPositionX()-1.0f);	backGround2->setPositionX(backGround1->getPositionX()+backGround1->getContentSize().width);	if(backGround2->getPositionX()<=0.0f)		backGround1->setPositionX(0.0f);}

添加角色
//添加player
player=Player::create();
player->setPosition(Point(visibleOrigin.x+2*BLOCK_SIZE,visibleOrigin.y+4*BLOCK_SIZE));
this->addChild(player,1);

添加地图
//设置地图,默认锚点在左下角
gameMap=GameMap::create();
gameMap->setPosition(visibleOrigin.x,visibleOrigin.y);
this->addChild(gameMap,1);

添加两个控制按钮
//添加滑行和跳跃按钮的事件
score=0; //初始化分数

slideBtn=Sprite::create("slideButton.png");
auto slideBtnTexture1=Sprite::create("slideButton.png")->getTexture();
auto slideBtnTexture2=Sprite::create("slideButtonPress.png")->getTexture();
slideBtnTextures.pushBack(slideBtnTexture1);
slideBtnTextures.pushBack(slideBtnTexture2);
slideBtn->setScale(0.5);
slideBtn->setPosition(Point(visibleOrigin.x+100,visibleOrigin.y+50));
this->addChild(slideBtn,2);

jumpBtn=Sprite::create("jumpButton.png");
auto jumpBtnTexture1=Sprite::create("jumpButton.png")->getTexture();
auto jumpBtnTexture2=Sprite::create("jumpButtonPress.png")->getTexture();
jumpBtnTextures.pushBack(jumpBtnTexture1);
jumpBtnTextures.pushBack(jumpBtnTexture2);
jumpBtn->setScale(0.5);
jumpBtn->setPosition(Point(visibleOrigin.x+visibleSize.width-100,visibleOrigin.y+50));
this->addChild(jumpBtn,2);

触摸检测,用于控制按钮
滑行时动态更换纹理
跳跃时给角色一个向上的速度,暂停动画,更换纹理
要注意的是,一开始只能二段跳,接了道具之后可以三段跳
bool GameScene::onTouchBegan(Touch *touch,Event *event)
{
auto touchPoint=touch->getLocation();
//检测是否触摸在按钮区域
if(slideBtn->getBoundingBox().containsPoint(touchPoint))
{
slideBtn->setTexture(slideBtnTextures.at(1));
player->slide();
}

if(jumpTimesgetBoundingBox().containsPoint(touchPoint))
{
if(isSound)
SimpleAudioEngine::getInstance()->playEffect("jump.wav"); //播放跳跃音效
jumpBtn->setTexture(jumpBtnTextures.at(1));
player->jump();
jumpTimes++;
}

return true;
}

void GameScene::onTouchEnded(Touch *touch,Event *event)
{
auto touchPoint=touch->getLocation();
//判断是释放时是否在按钮区域
if(slideBtn->getBoundingBox().containsPoint(touchPoint))
{
slideBtn->setTexture(slideBtnTextures.at(0));
player->run();
}

if(jumpBtn->getBoundingBox().containsPoint(touchPoint))
{
jumpBtn->setTexture(jumpBtnTextures.at(0));
}

}

碰撞检测
bool GameScene::onContactBegin(const PhysicsContact &contact)
{
jumpTimes=0; //落回地面就将已跳跃次数清零

//获得被碰撞物体,getShapeA getShapeB要尝试一下
auto target=contact.getShapeA()->getBody()->getNode();
if(target->getTag()==STAR)
{
//碰到星星就涨分,星星消失
gameMap->moveNode(target);
addScore(100); //拾取星星得100
}
else if(target->getTag()==NPC&&target->getPositionY()+target->getContentSize().height/2getPositionY()) //此处要用else if,只有当角色在怪物头上才能踩中
{
gameMap->moveNode(target);
addScore(150); //踩怪得150
}
else if(target->getTag()==NPC&&target->getPositionY()+target->getContentSize().height/2>=player->getPositionY()) //如果角色正面遇到怪物就挂了
gameOver();
else if(target->getTag()==TOOL)
{
jumpTotal=3;
auto toolIcon=Sprite::create("accelerate_state.png");
toolIcon->setPosition(Point(visibleOrigin.x+180,visibleOrigin.y+50));
this->addChild(toolIcon,2);
target->removeFromParent(); //道具只出现一次,从parent里面删除
addScore(300); //道具300
}

//落回地面恢复跑步状态
if(player->playerState==JUMP)
player->run();

return true;
}

碰撞检测的逻辑主要是
  • 判断碰撞的是砖块则继续奔跑
  • 判断碰撞的是怪物,并且是踩在投上,则消除怪物,得分
  • 判断碰撞的是拾取物,则消除拾取物,得分,如果是道具的话则获得三段跳的能力
  • 判断碰撞是正面遇到怪物,则游戏结束

游戏结束的逻辑
  • 正面遇到怪物
  • 落到屏幕底下
void GameScene::gameOver()
{
//游戏结束停止所有的调度器
gameMap->unscheduleAllSelectors();
this->unscheduleAllSelectors();
//播放游戏结束声音
if(isSound)
SimpleAudioEngine::getInstance()->playEffect("gameover.wav");

//游戏结束出现菜单
visibleSize=Director::getInstance()->getVisibleSize();
visibleOrigin=Director::getInstance()->getVisibleOrigin();

auto gameOverPanel=Node::create();
auto overLabel=Sprite::create("gameover.png");
overLabel->setPosition(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2+100);
gameOverPanel->addChild(overLabel);

auto backItem=MenuItemImage::create("back_to_menu.png","back_to_menu_press.png",[](Object *sender)
{
//用lambda表达式作为菜单函数回调
auto mainMenu=MainMenu::createScene();
TransitionScene *transition=TransitionFade::create(1.0f,mainMenu);
Director::getInstance()->replaceScene(transition);
});
auto backMenu=Menu::createWithItem(backItem);
backMenu->setPosition(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2-50);

gameOverPanel->addChild(backMenu);

gameOverPanel->setPositionY(visibleOrigin.y+visibleSize.height);
this->addChild(gameOverPanel,3);
//滑入gameover logo,注意node的锚点在左下角
gameOverPanel->runAction(MoveTo::create(0.5f,Vec2(visibleOrigin.x,visibleOrigin.y)));

}

其他逻辑
都放到update这个函数里面进行

角色被阻挡后赶到原来的位置

//当角色被挡道之后跟上原来的位置
float step=2.0f;
if(player->getPositionX()<2*BLOCK_SIZE)
player->setPositionX(player->getPositionX()+step);
if(player->getPositionX()>2*BLOCK_SIZE)
player->setPositionX(player->getPositionX()-step);

加分
void GameScene::addScore(float number)
{
if(isSound)
SimpleAudioEngine::getInstance()->playEffect("point.mp3"); //播放得分音效
score+=number;
scoreLabel->setString(String::createWithFormat("score: %d",score)->_string);
}

5 设置场景

设置游戏关卡、游戏角色和声音,这里懒得加xml配置文件存储。
//春天
auto springItem=MenuItemImage::create("spring_icon.png","spring_icon_press.png",[](Object *sender)
{
//修改关卡
level=SPRING;
textLevel->setString("level: Spring");
});


springItem->setPosition(visibleOrigin.x+visibleSize.width/4+35,visibleOrigin.y+visibleSize.height/4*3);
//冬天
auto winterItem=MenuItemImage::create("winter_icon.png","winter_icon_press.png",[](Object *sender)
{
//修改关卡
level=WINTER;
textLevel->setString("level: Winter");
});
winterItem->setPosition(visibleOrigin.x+visibleSize.width/4*3-35,visibleOrigin.y+visibleSize.height/4*3);
//男生
auto boyItem=MenuItemImage::create("boy1.png","boy_jump.png",[](Object *sender)
{
//修改角色
playerType=BOY;
textPlayer->setString("player: Boy");
});
boyItem->setPosition(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2-100);
//女生
auto girlItem=MenuItemImage::create("girl1.png","girl_jump.png",[](Object *sender)
{
//修改角色
playerType=GIRL;
textPlayer->setString("player: Girl");
});
girlItem->setPosition(visibleOrigin.x+visibleSize.width/2+200,visibleOrigin.y+visibleSize.height/2-100);

//声音开关
auto soundItem=MenuItemImage::create("sound_on.png","sound_off.png",[](Object *sender)
{
//修改声音
isSound=!isSound;
textSound->setString(isSound?"sound: On":"sound: Off");
});
soundItem->setPosition(visibleOrigin.x+soundItem->getContentSize().width/2,visibleOrigin.y+soundItem->getContentSize().height/2);


auto menu=Menu::create(backItem,springItem,winterItem,boyItem,girlItem,soundItem,NULL);
menu->setPosition(Point::ZERO);

this->addChild(menu);
通过全局变量与其他场景交互


6 关于场景

//添加动态背景
auto backGround=Sprite::create("about.jpg");
backGround->setPosition(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2);
auto repeatAnim=MoveBy::create(3.0f,Vec2(0,50));
backGround->runAction(RepeatForever::create(Sequence::create(repeatAnim,repeatAnim->reverse(),NULL)));
this->addChild(backGround,0);

//添加关于告示
auto aboutLabel=Sprite::create("aboutLabel.png");
aboutLabel->setPosition(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2);
this->addChild(aboutLabel,1);
auto text=LabelBMFont::create("author:tashaxing\nE-mail:tashaxing@163.com\n\nWish you have fun!","bitmapFontChinese.fnt");
text->setPosition(visibleOrigin.x+visibleSize.width/2,visibleOrigin.y+visibleSize.height/2);
this->addChild(text,2);
一些简介


效果图
















整个demo也做了蛮久的,很多图片和图标,配色都是我自己ps的,算是策划、美术和程序一人承担了。

源码下载
csdn: 跑酷游戏
github: parkour


推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • Win11扩展卷无法使用?解决扩展卷灰色问题的指南
    本文详细介绍了在Windows 11中遇到扩展卷灰色无法使用时的解决方案,帮助用户快速恢复磁盘扩展功能。 ... [详细]
  • 本题通过将每个矩形视为一个节点,根据其相对位置构建拓扑图,并利用深度优先搜索(DFS)或状态压缩动态规划(DP)求解最小涂色次数。本文详细解析了该问题的建模思路与算法实现。 ... [详细]
  • 最近团队在部署DLP,作为一个技术人员对于黑盒看不到的地方还是充满了好奇心。多次咨询乙方人员DLP的算法原理是什么,他们都以商业秘密为由避而不谈,不得已只能自己查资料学习,于是有了下面的浅见。身为甲方,虽然不需要开发DLP产品,但是也有必要弄明白DLP基本的原理。俗话说工欲善其事必先利其器,只有在懂这个工具的原理之后才能更加灵活地使用这个工具,即使出现意外情况也能快速排错,越接近底层,越接近真相。根据DLP的实际用途,本文将DLP检测分为2部分,泄露关键字检测和近似重复文档检测。 ... [详细]
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • 脑机接口(BCI)技术正逐步将科幻变为现实,从帮助听障人士恢复听力到使瘫痪者重新站立,甚至可能将多年的学习过程压缩至瞬间。本文探讨了这一前沿技术的现状、挑战及其未来前景。 ... [详细]
  • 探索12个能显著提升iPhone使用体验的隐藏技巧,掌握这些功能后,你会发现生活更加便捷高效。 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 卷积神经网络(CNN)基础理论与架构解析
    本文介绍了卷积神经网络(CNN)的基本概念、常见结构及其各层的功能。重点讨论了LeNet-5、AlexNet、ZFNet、VGGNet和ResNet等经典模型,并详细解释了输入层、卷积层、激活层、池化层和全连接层的工作原理及优化方法。 ... [详细]
  • 本文深入探讨了 Redis 的两种持久化方式——RDB 快照和 AOF 日志。详细介绍了它们的工作原理、配置方法以及各自的优缺点,帮助读者根据具体需求选择合适的持久化方案。 ... [详细]
  • 本文详细介绍了在企业级项目中如何优化 Webpack 配置,特别是在 React 移动端项目中的最佳实践。涵盖资源压缩、代码分割、构建范围缩小、缓存机制以及性能优化等多个方面。 ... [详细]
  • jQuery HooRay:一款自创的实用 jQuery 工具插件
    这款插件主要由作者在工作中积累的常用功能开发而成,旨在解决现有插件间的冲突及浏览器兼容性问题。通过整合和优化现有插件,确保其稳定性和高效性。 ... [详细]
  • 本文详细介绍了如何在WebStorm中配置File Watchers,以实现在编辑LESS文件时自动生成压缩后的CSS文件和对应的源映射(.map)文件。通过简单几步设置,可以大幅提升前端开发效率。 ... [详细]
author-avatar
一切皆空2502861573
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有