让子弹飞是我非常喜欢的一款游戏。今天的目标就是利用cocos2dx 3.0 和box2d 打造一款这样的类型游戏的Demo版。本来cocos2dx 3.0 已经封装了physicals模块,可是我在使用的过程中遇到了一些问题,比方子弹速度过快时候会出屏等,所以就认为还是直接封装box2d API来完毕这款Demo。

我主要封装了两个类,一个叫Box2dHandler, 这个类继承自Node和b2ContactListener, 是用来和box2d打交道的。能够用来创建方形,圆形的静态或者动态刚体。创建物理世界,以及处理碰撞的检測重任都交给这个类了。另外一个类叫B2Sprite, 也继承自Node,本来是想继承自Sprite的,可是在实现过程中发现有问题。就改成继承自Node。它的功能是用来粘合cocos2dx和Box2D, 起到一个中间的桥梁作用。这里要感谢一下<<cocos2d-x高级开发教程>>一书,这两个类基本从它移植而来,可是原书使用的是2.0版本号。所以还是要做一些改动。

好了,闲话到此为止。上代码。

首先是Box2dHandler。

  1. #ifndef __BOX2DHANDLER_H__
  2. #define __BOX2DHANDLER_H__
  3.  
  4. #include "cocos2d.h"
  5. #include "Box2D.h"
  6. #include "Box2dHandlerDelegate.h"
  7. #include "B2Sprite.h"
  8.  
  9. USING_NS_CC;
  10.  
  11. enum shape
  12. {
  13. box=1,
  14. circle=2,
  15. };
  16.  
  17. class Box2dHandler : public cocos2d::Node, public b2ContactListener
  18. {
  19.  
  20. private:
  21. b2World *m_world;
  22. typedef std::pair<b2Fixture*, b2Fixture*> MyContact;
  23. std::set<MyContact> m_contacts;
  24. public:
  25. bool init();
  26. bool initBox2D();
  27. void addBodyForSprite(B2Sprite* sprite, double density = 1.0, double friction = 0.9, double restituion = 0.1, shape type=box);
  28. void addFixtureForSprite(B2Sprite* sprite, double density = 1.0, double friction = 0.9, double restituion = 0.1, shape type=box);
  29. void addStaticBodyForSprite(B2Sprite* sprite, double density = 0.0);
  30. void dealCollision();
  31.  
  32. public:
  33. virtual void BeginContact(b2Contact * contact);
  34. virtual void EndContact(b2Contact * contact);
  35.  
  36. static Box2dHandler * handler();
  37. //void draw();
  38. void update(float dt);
  39. CC_SYNTHESIZE(Box2dHandlerDelegate*, m_delegate, Delegate);
  40.  
  41. };
  42.  
  43. #endif // __BOX2DHANDLER_H__

熟悉box2d的话,非常easy看清楚这个类就是封装了主要的Box2D操作。包含创建刚体,以及监听碰撞。

接下来是实现代码。

  1. #include "Box2dHandler.h"
  2. #include "HelloWorldScene.h"
  3. #define PTM_RATIO 32
  4.  
  5. Box2dHandler * Box2dHandler::handler()
  6. {
  7. static Box2dHandler * handler = NULL;
  8. if(handler == NULL)
  9. {
  10. handler = new Box2dHandler();
  11. handler->init();
  12. return handler;
  13. }
  14. else
  15. {
  16. return handler;
  17. }
  18. }
  19.  
  20. bool Box2dHandler::init()
  21. {
  22. this->initBox2D();
  23. this->scheduleUpdate();
  24. return true;
  25. }
  26.  
  27. bool Box2dHandler::initBox2D()
  28. {
  29. Size s = Director::getInstance()->getWinSize();
  30. b2Vec2 gravity;
  31. gravity.Set(0.0f, -10.0f);
  32.  
  33. m_world = new b2World(gravity);
  34. m_world->SetAllowSleeping(true);
  35. m_world->SetContinuousPhysics(true);
  36. m_world->SetContactListener(this);
  37.  
  38. b2BodyDef groundBodyDef;
  39. groundBodyDef.position.Set(0, 0);
  40.  
  41. b2Body* groundBody = m_world->CreateBody(&groundBodyDef);
  42.  
  43. b2EdgeShape groundBox;
  44.  
  45. //Bottom
  46. //groundBox.Set(b2Vec2(0, 0), b2Vec2(s.width/PTM_RATIO, 0));
  47. //groundBody->CreateFixture(&groundBox, 0);
  48.  
  49. //Top
  50. groundBox.Set(b2Vec2(0, s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO, s.height/PTM_RATIO));
  51. groundBody->CreateFixture(&groundBox, 0);
  52.  
  53. //Left
  54. groundBox.Set(b2Vec2(0, s.height/PTM_RATIO), b2Vec2(0,0));
  55. groundBody->CreateFixture(&groundBox, 0);
  56.  
  57. //Right
  58. groundBox.Set(b2Vec2(s.width/PTM_RATIO, s.height/PTM_RATIO), b2Vec2(s.width/PTM_RATIO, 0));
  59. groundBody->CreateFixture(&groundBox, 0);
  60.  
  61. return true;
  62. }
  63.  
  64. void Box2dHandler::addFixtureForSprite(B2Sprite* sprite, double density, double friction, double restitution, shape type)
  65. {
  66. b2PolygonShape spriteShape;
  67. Size size = sprite->getB2Sprite()->getContentSize() * sprite->getScale();
  68. spriteShape.SetAsBox(size.width / PTM_RATIO / 2, size.height / PTM_RATIO / 2);
  69.  
  70. b2CircleShape circle;
  71. circle.m_radius = (sprite->getB2Sprite()->getContentSize().width * sprite->getScale())/2/PTM_RATIO;
  72.  
  73. b2FixtureDef spriteShapeDef;
  74. if(type == box)
  75. spriteShapeDef.shape = &spriteShape;
  76. else
  77. spriteShapeDef.shape = &circle;
  78. spriteShapeDef.density = density;
  79. spriteShapeDef.restitution = restitution;
  80. spriteShapeDef.friction = friction;
  81.  
  82. b2Body * spriteBody = sprite->getB2Body();
  83. spriteBody->CreateFixture(&spriteShapeDef);
  84. }
  85.  
  86. void Box2dHandler::addBodyForSprite(B2Sprite* sprite, double density, double friction, double restitution, shape type)
  87. {
  88. b2BodyDef spriteBodyDef;
  89. spriteBodyDef.type = b2_dynamicBody;
  90. spriteBodyDef.position.Set(sprite->getPosition().x / PTM_RATIO, sprite->getPosition().y / PTM_RATIO);
  91. spriteBodyDef.userData = sprite;
  92.  
  93. b2Body* spriteBody = m_world->CreateBody(&spriteBodyDef);
  94. sprite->setB2Body(spriteBody);
  95. this->addFixtureForSprite(sprite, density, friction, restitution, type);
  96. }
  97.  
  98. void Box2dHandler::addStaticBodyForSprite(B2Sprite* sprite, double density)
  99. {
  100. b2BodyDef spriteBodyDef;
  101. spriteBodyDef.type = b2_staticBody;
  102. spriteBodyDef.position.Set(sprite->getPosition().x / PTM_RATIO, sprite->getPosition().y / PTM_RATIO);
  103. //spriteBodyDef.userData = sprite;
  104.  
  105. b2Body* spriteBody = m_world->CreateBody(&spriteBodyDef);
  106. sprite->setB2Body(spriteBody);
  107. this->addFixtureForSprite(sprite, density);
  108. }
  109.  
  110. void Box2dHandler::update(float dt)
  111. {
  112. m_world->Step(dt, 8, 8);
  113. std::vector<b2Body*> toDestory;
  114. for(b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
  115. {
  116. if(b->GetUserData() != NULL)
  117. {
  118. B2Sprite* sprite = static_cast<B2Sprite*>(b->GetUserData());
  119. b2Vec2 pos = b->GetPosition();
  120. float rotation = b->GetAngle() / 0.01745329252;
  121. sprite->setPosition(pos.x * PTM_RATIO, pos.y * PTM_RATIO);
  122. sprite->setRotation(rotation);
  123. if(b->GetPosition().y*PTM_RATIO<= -25)
  124. {
  125. toDestory.push_back(b);
  126. }
  127. }
  128. }
  129.  
  130. if(toDestory.size()>0)
  131. {
  132. for(int i = 0; i < toDestory.size(); i++)
  133. {
  134. B2Sprite* sp=static_cast<B2Sprite*>( toDestory.at(i)->GetUserData());
  135. if(sp != NULL)
  136. sp->removeFromParentAndCleanup(true);
  137. m_world->DestroyBody(toDestory.at(i));
  138. }
  139. toDestory.clear();
  140. }
  141.  
  142. this->dealCollision();
  143. }
  144.  
  145. void Box2dHandler::BeginContact(b2Contact * contact)
  146. {
  147. CCLog("start");
  148. B2Sprite* spa = static_cast<B2Sprite*>(contact->GetFixtureA()->GetBody()->GetUserData());
  149. B2Sprite* spb = static_cast<B2Sprite*>(contact->GetFixtureB()->GetBody()->GetUserData());
  150.  
  151. if(spa != NULL && spb != NULL)
  152. {
  153. MyContact myContact(contact->GetFixtureA(), contact->GetFixtureB());
  154. m_contacts.insert(myContact);
  155. }
  156. }
  157.  
  158. void Box2dHandler::EndContact(b2Contact* contact)
  159. {
  160. CCLog("end");
  161. MyContact myContact(contact->GetFixtureA(), contact->GetFixtureB());
  162. m_contacts.erase(myContact);
  163. }
  164.  
  165. void Box2dHandler::dealCollision()
  166. {
  167. if(m_delegate != NULL && m_contacts.size()>0)
  168. {
  169. std::set<MyContact>::iterator it;
  170. for(it = m_contacts.begin(); it != m_contacts.end(); ++it)
  171. {
  172. B2Sprite* bullet = static_cast<B2Sprite*>(it->first->GetBody()->GetUserData());
  173. B2Sprite* actor = static_cast<B2Sprite*>(it->second->GetBody()->GetUserData());
  174. if(bullet->getTag() == kTagBulletBase && (actor->getTag() == kTagRedEnemy || actor->getTag() == kTagBlueEnemy || actor->getTag() == kTagYellowEnemy))
  175. m_delegate->CollisionEvent(bullet, actor);
  176. else if((bullet->getTag() == kTagRedEnemy || bullet->getTag() == kTagBlueEnemy || bullet->getTag() == kTagYellowEnemy) && actor->getTag() == kTagBulletBase )
  177. m_delegate->CollisionEvent(actor, bullet);
  178. }
  179. }
  180. m_contacts.clear();
  181. }

简单解释下:

  1. Box2dHandler * Box2dHandler::handler()

构造函数,内存管理交给cocos2dx

  1. bool Box2dHandler::initBox2D()

设置好重力场,创建物理世界m_world, 以及定义好屏幕边界为可碰撞的静态刚体。

  1. void Box2dHandler::addBodyForSprite(B2Sprite* sprite, double density, double friction, double restitution, shape type)

创建动态刚体,有方形和圆形两种选择。

  1. void Box2dHandler::addFixtureForSprite(B2Sprite* sprite, double density, double friction, double restitution, shape type)

为刚体创建外观并设置刚体属性。

  1. void Box2dHandler::update(float dt)

更新物理世界,并同步刚体位置到cocos2dx中精灵,当中的桥梁就是B2Sprite。

  1. void Box2dHandler::BeginContact(b2Contact * contact)
  1. void Box2dHandler::EndContact(b2Contact* contact)

物理碰撞检測的回调方法。

  1. void Box2dHandler::dealCollision()

自己定义的碰撞处理方法。

就这么多。非常easy明了。接下来看看B2Sprite的代码

  1. #include "cocos2d.h"
  2. #include "Box2D.h"
  3. USING_NS_CC;
  4.  
  5. enum Enemy_Color
  6. {
  7. k_red = 0,
  8. k_blue = 1,
  9. k_yellow = 2,
  10. };
  11.  
  12. class B2Sprite : public cocos2d::Node
  13. {
  14. public:
  15.  
  16. static B2Sprite* create(CCTexture2D * texture);
  17. static B2Sprite* create(const char* pngFile);
  18. bool init(const char* pngFile);
  19. bool init(CCTexture2D* texture);
  20. CCActionInterval* createAnimation(const char* plist,int frames);
  21. CCActionInterval* createZombileAnimation(const char* plist, int frames, Enemy_Color color);
  22.  
  23. static B2Sprite* create(const char* plist, int frames, Enemy_Color color);
  24. bool init(const char* plist, int frames, Enemy_Color color);
  25.  
  26. CC_SYNTHESIZE_READONLY(Sprite*, m_sprite, B2Sprite);
  27. CC_SYNTHESIZE(b2Body*, m_b2Body, B2Body); // 物理实际的“物体”
  28. CC_SYNTHESIZE(bool, m_isDead, IsDead);
  29. CC_SYNTHESIZE(bool, m_isAlive, IsAlive);
  30. };
  31.  
  32. #endif

主要内容在这里

  1. CC_SYNTHESIZE_READONLY(Sprite*, m_sprite, B2Sprite);
  2. CC_SYNTHESIZE(b2Body*, m_b2Body, B2Body); // 物理实际的“物体”

我们能够看到B2Sprite一方面挂接了一个Sprite用于显示刚体,另外一方面有挂接了一个刚体对象m_b2Body, 所以它就起着一个桥梁的作用。

实现代码就不给出了。由于都是些细节性的方法,是用来写这个Demo的。大家全然能够依据自己须要来封装自己的B2Sprite版本号。

好了完毕了这两个类的封装。接下来就是完毕我们的Demo了。

我建立一个叫HelloWorldScene的Layer来承载这个游戏Demo。

  1. #ifndef __HELLOWORLD_SCENE_H__
  2. #define __HELLOWORLD_SCENE_H__
  3.  
  4. #include "cocos2d.h"
  5. #include "Box2D.h"
  6. #include "VisibleRect.h"
  7. #include "cocos-ext.h"
  8. #include "Box2dHandler.h"
  9. using namespace cocos2d;
  10.  
  11. enum {
  12. kTagParentNode = 1,
  13. kTagBulletParentNode=2,
  14. kTagHandler = 3,
  15. kTagFloor = 100,
  16. kTagFloor2 = 101,
  17. kTagRedEnemy = 102,
  18. kTagBlueEnemy = 103,
  19. kTagYellowEnemy = 104,
  20. kTagBulletBase = 500,
  21. };
  22.  
  23. class HelloWorld : public cocos2d::Layer, public Box2dHandlerDelegate
  24. {
  25. public:
  26. // there's no 'id' in cpp, so we recommend returning the class instance pointer
  27. static cocos2d::Scene* createScene();
  28. HelloWorld();
  29. ~HelloWorld();
  30.  
  31. // Touch process
  32. bool onTouchBegan(Touch* touch, Event* pEvent);
  33. void onTouchEnded(Touch* touch, Event* pEvent);
  34.  
  35. virtual void CollisionEvent(B2Sprite*, B2Sprite*);
  36. void HelloWorld::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity);
  37.  
  38. };
  39.  
  40. #endif // __HELLOWORLD_SCENE_H__

我将创建刚体的任务都放在构造函数中,CollisionEvent是处理碰撞的回调方法。LauchBomb是发射子弹的方法。

接下来看实现。

  1. #include "HelloWorldScene.h"
  2.  
  3. #define PTM_RATIO 32
  4. USING_NS_CC;
  5.  
  6. Scene* HelloWorld::createScene()
  7. {
  8. auto scene = Scene::create();
  9. auto layer = new HelloWorld();
  10. scene->addChild(layer);
  11. layer->release();
  12. return scene;
  13. }
  14.  
  15. HelloWorld::HelloWorld()
  16. {
  17. auto dispatcher = Director::getInstance()->getEventDispatcher();
  18. auto touchListener = EventListenerTouchOneByOne::create();
  19. touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
  20. //touchListener->onTouchMoved = CC_CALLBACK_2(MapLayer::onTouchMoved, this);
  21. touchListener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
  22. dispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);
  23.  
  24. Sprite* bg = Sprite::create("bg3.png");
  25. addChild(bg, -1);
  26. bg->setPosition(ccp( VisibleRect::center().x, VisibleRect::center().y));
  27.  
  28. Box2dHandler * handler = Box2dHandler::handler();
  29. handler->setDelegate(this);
  30. handler->setTag(kTagHandler);
  31. this->addChild(handler);
  32.  
  33. B2Sprite * floor = B2Sprite::create("floor.png");
  34. floor->setTag(kTagFloor);
  35. floor->setPosition(300, 350);
  36. handler->addStaticBodyForSprite(floor);
  37. addChild(floor);
  38.  
  39. B2Sprite * floor2 = B2Sprite::create("floor2.png");
  40. floor2->setTag(kTagFloor2);
  41. floor2->setPosition(450, 250);
  42. handler->addStaticBodyForSprite(floor2);
  43. addChild(floor2);
  44.  
  45. B2Sprite * redEnemy = B2Sprite::create("Zombie", 16, k_red);
  46. redEnemy->setTag(kTagRedEnemy);
  47. redEnemy->setPosition(442,500);
  48. handler->addBodyForSprite(redEnemy);
  49. addChild(redEnemy);
  50.  
  51. B2Sprite * blueEnemy = B2Sprite::create("Zombie", 16, k_blue);
  52. blueEnemy->setTag(kTagBlueEnemy);
  53. blueEnemy->setPosition(310,500);
  54. handler->addBodyForSprite(blueEnemy);
  55. addChild(blueEnemy);
  56.  
  57. B2Sprite * yellowEnemy = B2Sprite::create("Zombie", 16, k_yellow);
  58. yellowEnemy->setTag(kTagYellowEnemy);
  59. yellowEnemy->setPosition(330,500);
  60. handler->addBodyForSprite(yellowEnemy);
  61. addChild(yellowEnemy);
  62. }
  63.  
  64. HelloWorld::~HelloWorld()
  65. {
  66. }
  67.  
  68. void HelloWorld::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
  69. {
  70. B2Sprite * sprite = B2Sprite::create("bullet.png");
  71. sprite->setScale(0.3);
  72. sprite->setPosition(ccp(position.x, position.y));
  73. Box2dHandler * handler = (Box2dHandler*)(this->getChildByTag(kTagHandler));
  74. handler->addBodyForSprite(sprite, 1.0, 0.3, 0.8, circle);
  75. sprite->getB2Body()->SetLinearVelocity(velocity);
  76. sprite->getB2Body()->SetBullet(true);
  77. sprite->setTag(kTagBulletBase);
  78. addChild(sprite);
  79. }
  80.  
  81. bool HelloWorld::onTouchBegan(Touch* touch, Event* pEvent)
  82. {
  83. return true;
  84. }
  85.  
  86. void HelloWorld::onTouchEnded(Touch* touch, Event* pEvent)
  87. {
  88. Point p = touch->getLocation();
  89. b2Vec2 target(p.normalize().x * 100, p.normalize().y*100);
  90. b2Vec2 v = target;
  91. b2Vec2 source(0, 0);
  92. LaunchBomb(source, v);
  93. }
  94.  
  95. // a is bullet
  96. void HelloWorld::CollisionEvent(B2Sprite*a, B2Sprite*b)
  97. {
  98. if(a->getPositionX() < b->getPositionX())
  99. b->getB2Body()->ApplyLinearImpulse(b2Vec2(100,0), b->getB2Body()->GetPosition(), true);
  100. else if(a->getPositionX() > b->getPositionX())
  101. b->getB2Body()->ApplyLinearImpulse(b2Vec2(-100,0), b->getB2Body()->GetPosition(), true);
  102.  
  103. }

  1. HelloWorld::HelloWorld()

中我放置了两个镜头刚体作为floor, 然后在上面放了几个敌人。当然,假设要做一个正式的游戏,关卡数据要在外面编辑好,然后读取进来。这里只写个Demo,就没有编辑关卡了。

  1. void HelloWorld::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)

创建了一个子弹刚体。这种方法在每次触摸屏幕都会触发。

  1. void HelloWorld::CollisionEvent(B2Sprite*a, B2Sprite*b)

碰撞检測回调方法,这里做的处理是: 假设子弹和敌人产生碰撞,假设敌人在子弹坐标,就给它一个水平向左的冲量,反之给它一个向右的冲量,让它掉下平台。

能够看到,真正的Demo代码是很少的。

接下来上图。

设计一颗子弹

好了,这就是本章的所有内容。源代码已经上传到群 216208142 空间,有须要的读者能够加群来获取。

让子弹飞Demo版的更多相关文章

  1. 转:基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴等)【模式识别中的翘楚】

    文章来自于:http://blog.renren.com/share/246648717/8171467499 基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴 ...

  2. java springMVC 极致验证 非demo版

    最近公司项目需要,做了个极致验证,自己在此做下记录. 先上效果图: 它的官网:http://www.geetest.com/   里面有 身份验证.行为验证,  我这使用的为行为验证. 技术文档:ht ...

  3. 闯越自动签到demo版补充说明

    demo代码:https://www.cnblogs.com/canmeng/p/11000548.html 定位出错是由于cookie 我重新登录账号过,cookies的值就变了 当时没注意cook ...

  4. 基于python3.7的一个闯越自动签到脚本--demo版

    望指正demo的定位,有时候会抽风无法接受我的定位信息 #! /usr/bin/python3 # -*- coding:UTF- -*- # time : // : # file : chuangy ...

  5. Demo 版

    Demo1   美食网站 Demo2   12301智慧旅游公共服务平台 Demo3   react_and_koa example

  6. 捕鱼达人Demo版下载

    链接:https://pan.baidu.com/s/1ihHhikpFXiNJMxa26E8qBw 提取码:npj6

  7. 自制EF(iShare Demo版)

    由于公司使用的所有技术都比较倾向于使用原生,不怎么借用其他第三方框架(无论是前端布局,样式,到后台的框架).公司也算比较小型的没有太大的项目 可以让我们进行团队合作项目,几乎是一人接手一个项目.然后自 ...

  8. 【Java】Swing+IO流实现一个简单的文件加密程序(demo版)

    留着参考 EncrytService package com.my.service; import java.io.File; import java.io.FileInputStream; impo ...

  9. 【flask】使用配置类管理app测试环境-demo版

    如果对app.config是什么还心有疑惑,或者对于这种配置方式很陌生,参考:flask项目配置 app.config classConfig.py: class BaseConfig(object) ...

随机推荐

  1. 【转】实践最有效的提高Android Studio运行、编译速度方案

    原文:https://blog.csdn.net/xwh_1230/article/details/60961723 实践最有效的提高Android Studio运行.编译速度方案 最有效提升Andr ...

  2. mysql千万级表关联优化

    MYSQL一次千万级连表查询优化(一) 概述: 交代一下背景,这算是一次项目经验吧,属于公司一个已上线平台的功能,这算是离职人员挖下的坑,随着数据越来越多,原本的SQL查询变得越来越慢,用户体验特别差 ...

  3. day5模块学习--yaml文件处理

    yaml文件处理(http://pyyaml.org/wiki/PyYAMLDocumentation)     摘要: 本文讲的是yaml在python上的使用教程详解, YAML是一种容易人类阅读 ...

  4. 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 D.寻找-树上LCA(树上a到b的路径上离c最近的点)

    链接:https://ac.nowcoder.com/acm/contest/558/D来源:牛客网 寻找 小猫在研究树. 小猫在研究树上的距离. 给定一棵N个点的树,每条边边权为1. Q次询问,每次 ...

  5. 【原创】记一次MySQL大表高并发写入引发CPU飙升的排障过程

    目录 一.故障现象... 1 二.初步分析... 2 三.排障过程... 2 1.排查是否QPS或insert并发请求上升导致问题发生... 2 2.排查是否锁资源等待或block导致了insert变 ...

  6. ssm框架常见问题

    搭建SSM框架时,总是遇到这样那样的问题,有的一眼就能看出来,有的需要经验的积累.现将自己搭建SSM框架时遇到的典型问题总结如下: 一.Struts2框架下的action中无法使用@Autowired ...

  7. web服务端安全之暴力破解

    一.暴力破解 指攻击者通过遍历或字典的方式,向目标发起大量请求,通过判断返回数据包的特征来找出正确的验证信息,从而绕过验证机制. 二.常见场景 用户登录处的账号密码暴力破解: 人机验证机制容易绕过,如 ...

  8. python opencv3 特征提取与描述 DoG SIFT hessian surf

    git:https://github.com/linyi0604/Computer-Vision DoG和SIFT特征提取与描述 # coding:utf-8 import cv2 # 读取图片 im ...

  9. CF946D Timetable 动态规划

    预处理出每一行去掉$k$个1能获得的最小代价 之后做一次分组背包$dp$即可 预处理可以选择暴力枚举区间... 复杂度$O(n^3)$ #include <set> #include &l ...

  10. BZOJ.3498.[PA2009]Cakes(三元环 枚举)

    题目链接 感觉我可能学的假的(复杂度没问题,但是常数巨大). 一个比较真的说明见这儿:https://czyhe.me/blog/algorithm/3-mem-ring/3-mem-ring/. \ ...