Skip to content

Instantly share code, notes, and snippets.

@sknjpn
Created June 28, 2017 14:34
Show Gist options
  • Save sknjpn/58d0b5ffde1de91e2331a8c32650ebf6 to your computer and use it in GitHub Desktop.
Save sknjpn/58d0b5ffde1de91e2331a8c32650ebf6 to your computer and use it in GitHub Desktop.
# include <Siv3D.hpp> // OpenSiv3D v0.1.5
# include <HamFramework.hpp>
struct Unit
{
Unit(const Vec2& _pos)
: pos(_pos)
, isPlant(RandomBool(0.95))
, angle(RandomVec2(1.0))
, v(RandomVec2(0.0))
, energy(Random(25, 100))
, timer1(Random(150.0, 300.0))
, target(NULL)
{}
Unit(const Unit* _u)
: pos(_u->pos)
, isPlant(RandomBool(0.01) ? !_u->isPlant : _u->isPlant)
, angle(RandomVec2(1.0))
, v(RandomVec2(1.0))
, energy(Random(25, 50))
, timer1(Random(150.0, 300.0))
, target(NULL)
{}
Vec2 pos;
bool isPlant;
Vec2 angle;
Vec2 v;
double energy;
Unit* target;
//AI
double timer1;
};
void Main()
{
Window::SetTitle(L"Lonely Creatures");
Window::Resize(1280, 720);
Window::SetBaseSize(Window::Size());
Graphics::SetBackground(Palette::Skyblue);
Array<Unit> units;
const double width = 64.0;
const double sizeX = 512;
const double sizeY = 512;
for (int i = 0; i < 200; i++)
units.push_back(RandomVec2(sizeX, sizeY));
Grid<Array<Unit*>> data(int(sizeX / width) + 1, int(sizeY / width) + 1);
Camera2D camera;
while (System::Update())
{
for (auto& u : units)
{
if (u.isPlant)
{
u.energy += 0.1;
}
else
{
if (u.target == NULL)
{
u.timer1 -= 1.0;
if (u.timer1 < 0)
{
u.timer1 = Random(150.0, 300.0);
u.angle = RandomVec2(1.0);
}
}
else
{
if ((u.target->pos - u.pos).length() < 8.0)
{
u.target->energy -= 5.0;
u.energy += 1.5;
}
u.angle = (u.target->pos - u.pos).normalized();
}
u.energy -= 0.1;
u.v += u.angle*0.05;
}
u.v /= 1.1;
}
for (int i = 0; i < units.size(); i++)
{
auto& u = units[i];
if (u.energy > 100.0)
{
u.energy -= 50.0;
units.push_back(&u);
}
}
Erase_if(units, [&](Unit& u) {return u.energy <= 0.0; });
for (auto& p : step(data.size())) data[p.x][p.y].clear();
for (auto& u : units)
{
//運動処理
u.pos += u.v;
if (u.pos.x < 0) u.pos.x = 0.0;
if (u.pos.y < 0) u.pos.y = 0.0;
if (u.pos.x > sizeX) u.pos.x = sizeX;
if (u.pos.y > sizeY) u.pos.y = sizeY;
data[int(u.pos.x / width)][int(u.pos.y / width)].push_back(&u);
}
for (auto& u1 : units)
{
u1.target = NULL;
for (int x = Max(0, int(u1.pos.x / width) - 1); x <= Min(int(sizeX / width), int(u1.pos.x / width) + 1); x++)
{
for (int y = Max(0, int(u1.pos.y / width) - 1); y <= Min(int(sizeY / width), int(u1.pos.y / width) + 1); y++)
{
for (auto& u2 : data[x][y])
{
if (&u1 != u2 && !(u1.pos - u2->pos).isZero())
{
const double length = (u1.pos - u2->pos).length();
if (length < 8.0) u1.v += (u1.pos - u2->pos).normalized()*(16.0 - length)*0.01;
if (!u1.isPlant && u2->isPlant && (u1.pos - u2->pos).length() < 16.0 && u1.angle.cross((u2->pos - u1.pos).normalized()) < 0.7)
{
if (u1.target == NULL || (u1.pos - u1.target->pos).length() > (u1.pos - u2->pos).length()) u1.target = u2;
}
}
}
}
}
}
camera.update();
{
auto t = camera.createTransformer();
for (double x = 0; x <= sizeX; x += width) Line(x, 0, x, sizeY).draw(2, Palette::Gray);
for (double y = 0; y <= sizeY; y += width) Line(0, y, sizeX, y).draw(2, Palette::Gray);
for (const auto& u : units)
{
const double theta = atan2(u.angle.y, u.angle.x);
if (!u.isPlant) Circle(u.pos, 24).drawPie(theta + 0.78, 1.57, ColorF(Palette::Red, 0.5));
}
for (const auto& u : units)
{
const Color& color = u.isPlant ? Palette::Green : Palette::Orange;
Line(0.0, 0.0, 8.0, 0.0).movedBy(u.pos.movedBy(-4.0, -6.0)).draw(Palette::Black);
Line(0.0, 0.0, u.energy*0.08, 0.0).movedBy(u.pos.movedBy(-4.0, -6.0)).draw(Palette::Yellow);
Circle(u.pos, 4).draw(color).drawFrame(1, Palette::Black);
}
RectF(sizeX, sizeY).drawFrame(0, 2, Palette::Black);
}
camera.draw();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment