Skip to content

Instantly share code, notes, and snippets.

@tokoroten
Last active January 10, 2018 11:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tokoroten/af922e4488104c7e8495290cc3c7de73 to your computer and use it in GitHub Desktop.
Save tokoroten/af922e4488104c7e8495290cc3c7de73 to your computer and use it in GitHub Desktop.
box2dで遊んでみる
# include <Siv3D.hpp>
# include <HamFramework.hpp>
class Ball
{
public:
static const double SIZE;
static const Polygon POLYGONS[];
static const Color COLORS[];
static Font FONT;
static const int CHAIN_TIME;
static const int BOMBED_TIME;
int mColor = 0;
bool isLive = true;
bool isBurning = false;
int mBurningCounter = 0;
int mConnectedCount = 0;
private:
PhysicsBody mBody;
public:
static void classInit()
{
FONT = Font(12);
}
public:
Ball(PhysicsBody body, int color) :
mBody(body), mColor(color)
{
mBody.setDamping(0.8);
}
~Ball() {
}
Ball(const Ball& ball):
mColor(ball.mColor), isLive(ball.isLive), mBody(ball.getBody()), mConnectedCount(0)
{}
Ball &operator=(const Ball &ball)
{
mColor = ball.mColor;
isLive = ball.isLive;
mBody = ball.mBody;
mConnectedCount = ball.mConnectedCount;
isBurning = ball.isBurning;
mBurningCounter = ball.mBurningCounter;
return *this;
}
const bool operator==(const Ball& ball) const{
return &mBody == &ball.getBody();
}
const PhysicsBody& getBody() const { return mBody; }
PhysicsBody& getBodyUnsafe() { return mBody; }
void setLinkedNum(int count) {
mConnectedCount = count;
}
void run()
{
if (isLive == false) {
return;
}
{
const auto& center = Vec2(0, 0);
const auto deltaVec = center - mBody.getPos();
//const auto r = deltaVec.length();
const auto nVec = deltaVec.normalized();
const auto f = nVec * 100.0 * SIZE * SIZE;
mBody.applyForce(f);
}
if (mConnectedCount >= 3) {
isBurning = true;
}
if (isBurning) {
mBurningCounter++;
}
if (mBurningCounter >= BOMBED_TIME) {
isLive = false;
}
}
void draw() const
{
if (isLive == false) {
return;
}
const auto color = COLORS[mColor];
const auto pos = mBody.getPos();
const auto angle = mBody.getAngle();
auto polygon = POLYGONS[mColor];
polygon = polygon.rotated(angle);
polygon.draw(pos, isBurning ? Palette::White : color);
polygon.drawFrame(pos, SIZE/10, Palette::White);
}
void drawFont() const
{
wchar_t ws[4];
swprintf_s(ws, 4, L"%d", mConnectedCount);
FONT.drawAt(ws, mBody.getPos(), Palette::Black);
}
void bombedFrom(Vec2 &pos)
{
const auto dv = mBody.getPos() - pos ;
const auto r = dv.length() + 0.001;
const auto v = dv.normalized();
const auto f = v / (r*r) * 1000000;
mBody.applyForce(f);
}
};
Font Ball::FONT;
const double Ball::SIZE = 2.0;
const int Ball::CHAIN_TIME = 20;
const int Ball::BOMBED_TIME = 120;
const Polygon Ball::POLYGONS[] = {
Geometry2D::CreateNgon(3, Ball::SIZE),
Geometry2D::CreateNgon(4, Ball::SIZE),
Geometry2D::CreateNgon(5, Ball::SIZE),
Geometry2D::CreateNgon(16, Ball::SIZE),
Geometry2D::CreatePlus(Ball::SIZE, Ball::SIZE*0.2),
Geometry2D::CreateStar(Ball::SIZE),
};
const Color Ball::COLORS[] = {
Palette::Red,
Palette::Green,
Palette::Blue,
Palette::Yellow,
Palette::Cyan,
Palette::Magenta,
};
class BallGame
{
private:
PhysicsWorld mWorld;
Array<Ball*> mBallList;
Ball* mHold;
public:
BallGame():
mHold(new Ball(mWorld.createCircle({0, 0}, Ball::SIZE), 0))
{
init();
};
~BallGame() {};
void init()
{
Ball::classInit();
mWorld.setGravity({ 0,0 });
for (auto i : step(100))
{
const auto pos = (RandomVec2() + RandomVec2()) * 20 * Ball::SIZE;
const auto color = int(Random() * 6);
const auto body = mWorld.createCircle(pos, Ball::SIZE);
mBallList.push_back(new Ball(body, color));
}
const auto pos = Mouse::PosF();
const auto color = int(Random() * 6);
const auto body = mWorld.createCircle(pos, Ball::SIZE);
mHold = new Ball(body, color);
}
void fireCheck()
{
for (auto& ball1 : mBallList) {
const auto pos1 = ball1->getBody().getPos();
auto linked = 0;
for (auto& ball2 : mBallList){
if (ball1 == ball2) {
continue;
}
if (ball2->mBurningCounter == Ball::BOMBED_TIME -1)
{
ball1->bombedFrom(ball2->getBody().getPos());
}
if (ball1->mColor != ball2->mColor) {
continue;
}
const auto pos2 = ball2->getBody().getPos();
const auto l = (pos2 - pos1).length();
const auto size = Ball::SIZE * 2.2;
if (l < size) {
linked++;
if (ball2->mBurningCounter >= Ball::CHAIN_TIME) {
linked = 10;
}
}
}
ball1->setLinkedNum(linked);
}
}
void removeDeadBall()
{
Array<Ball*> removed;
for (auto it = mBallList.begin(); it != mBallList.end(); ) {
if ((*it)->isLive == false) {
removed.push_back(*it);
it = mBallList.erase(it);
}
else {
++it;
}
}
for (auto& ball : removed) {
delete ball;
}
}
void run()
{
// update hold
mHold->getBodyUnsafe().setPos(Mouse::PosF());
// input
if (Input::MouseL.clicked) {
mBallList.push_back(mHold);
const auto pos = Mouse::PosF();
const auto color = int(Random() * 6);
const auto body = mWorld.createCircle(pos, Ball::SIZE);
mHold = new Ball(body, color);
}
if (Input::Key1.pressed)
{
const auto pos = RandomVec2() * 100 * Ball::SIZE;
const auto color = int(Random() * 6);
auto body = mWorld.createCircle(pos, Ball::SIZE);
body.applyLinearImpulse(-pos * 100000000);
mBallList.push_back(new Ball(body, color));
}
if (Input::Key2.clicked)
{
const auto base_pos = RandomVec2() * 80 * Ball::SIZE;
for (auto i : step(20))
{
const auto pos = base_pos + RandomVec2()*20*Random();
const auto color = int(Random() * 6);
auto body = mWorld.createCircle(pos, Ball::SIZE);
body.applyLinearImpulse(-base_pos * 100000000);
mBallList.push_back(new Ball(body, color));
}
}
removeDeadBall();
// move blls
for (auto& ball : mBallList) {
ball->run();
}
fireCheck();
mWorld.update();
}
void draw() const
{
mHold->draw();
for (const auto& ball : mBallList) {
ball->draw();
//ball.drawFont();
}
}
};
void Main()
{
//ScalableWindow::Setup({1920, 1080});
Window::Resize(1920, 1080);
CameraBox2D bx2dCamera(Vec2(0, 0), 3.0);
auto game = BallGame();
game.init();
const auto font = Font(12);
while (System::Update())
{
bx2dCamera.update();
{
const auto t1 = bx2dCamera.createTransformer();
const auto t2 = ScalableWindow::CreateTransformer();
game.run();
game.draw();
}
bx2dCamera.draw(Palette::Orange);
//draw some ui here
font(Profiler::FPS(), L"fps").draw();
}
}
@tokoroten
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment