Skip to content

Instantly share code, notes, and snippets.

@wx257osn2
Created May 20, 2015 01:24
Show Gist options
  • Save wx257osn2/03070a196bea3c541901 to your computer and use it in GitHub Desktop.
Save wx257osn2/03070a196bea3c541901 to your computer and use it in GitHub Desktop.
ねるねるねるね with Direct2D1.0
#include <will/_2dim.hpp>
#include <will/com.hpp>
#include <vector>
#include <cstdint>
#include <cmath>
#include <d2d1.h>
std::int64_t timer;
double w, h;
static const double neData[] = {55.741471, 10.28401, 4.79822, 0.021, 9.59645, 0.0421, 14.394669, 0.0631, -5.261209, 4.31419, -10.522419, 8.62839, -15.783629, 12.94258, 0, 0, 6.37659, -4.48255, 13.70019, -2.33598, 3.661809, 1.07329, 5.271739, 2.856843, 5.934649, 4.458883, 0.66292, 1.60204, 0.37881, 3.022567, 0.25254, 3.369807, -0.25254, 0.69448, -0.78921, 5.65708, -9.733549, 6.74007, -4.62955, 0.56055, -5.44009, -1.65231, -5.36171, -2.81243, 0.11817, -1.74924, 1.20883, -3.06318, 3.54164, -3.04376, 2.10739, 0.0175, 3.04624, 1.34161, 3.63023, 2.19392, 0.584, 0.85232, 0.72605, 1.81512, 0.97859, 2.85684};
static const double ruData[] = {47.547019, 15.301239, 3.78807, -0.0421, 7.57615, -0.0842, 11.36422, -0.12627, -3.40926, 5.3033, -6.81853, 10.6066, -10.22779, 15.9099, 4.12479, -3.43031, 8.0286, -6.13457, 12.69003, -9.34391, 0, 0, 4.54569, -3.12515, 6.69227, -3.4724, 3.77923, -0.61136, 5.3033, 2.58852, 5.3033, 2.58852, 0, 0, 1.76776, 2.65165, 0.31567, 9.65958, -1.45209, 7.00794, -7.00793, 4.48255, -7.00793, 4.48255, -1.53407, -0.82854, -1.8324, -2.22846, -0.44195, -3.78807, 0, 0, 1.95718, -2.58851, 5.99779, -0.94702, 4.04061, 1.6415, 5.93464, 3.15673, 5.93464, 3.15673};
static const double stick[] = {52.534649, 9.619129, 0, 26.01143, 0, 26.01143, 0, 26.01143};
will::two_dim::xy<double> stickRu = {42., -30.};
will::two_dim::xy<double> fuPos ={-120. / 2, -75. / 2};
int dataSize = 10;
double time = 0.;
int sendRu = 0;
int curRu = -5;
double pumpPos = 0;
int u = 4;
int pushed = -1;
//static const double sPos[] = {w - 125, w - 120, w - 120};
//public var sName : Array = ["Perfect", "Cool", "Good"];
bool next = false;//Ne.Ru
will::com_ptr<ID2D1SolidColorBrush> brush;
class path_geometry{
will::com_ptr<ID2D1PathGeometry> path;
ID2D1GeometrySink* sink = nullptr;
public:
explicit path_geometry(ID2D1PathGeometry* p):path(p){}
path_geometry& operator=(ID2D1PathGeometry* p){path = p;return *this;}
void reset(){path.reset();}
template<typename F>
HRESULT operator()(const D2D1_POINT_2F& point, F&& f, D2D1_FIGURE_BEGIN beg = D2D1_FIGURE_BEGIN_FILLED, D2D1_FIGURE_END end = D2D1_FIGURE_END_OPEN){
auto hr = path->Open(&sink);
if(FAILED(hr))
return hr;
sink->BeginFigure(point, beg);
f(sink);
sink->EndFigure(end);
return sink->Close();
}
ID2D1PathGeometry* get(){return path.get();}
}geometry{nullptr};
will::com_ptr<ID2D1SolidColorBrush> create_solid_color_brush(ID2D1HwndRenderTarget* rt, const D2D1_COLOR_F& col, const D2D1_BRUSH_PROPERTIES& prop = D2D1::BrushProperties()){
return will::com_create_resource<ID2D1SolidColorBrush>([&](ID2D1SolidColorBrush** x){return rt->CreateSolidColorBrush(col, prop, x);});
}
path_geometry create_geometry(ID2D1Factory* rt){
return path_geometry{will::com_create_resource<ID2D1PathGeometry>([&](ID2D1PathGeometry** x){return rt->CreatePathGeometry(x);})};
}
double linear(double a, double b, double g){
return a * (1 - g) + b * g;
}
void drawNeru(ID2D1HwndRenderTarget* rt, double x, double y, double s, double g, float stroke_width){
double dx = x + (fuPos.x + linear(neData[0], ruData[0], g))*s;
double dy = y + (fuPos.y + linear(neData[1], ruData[1], g))*s;
double cx = 0, cy = 0;
geometry(D2D1::Point2F(dx, dy), [&](ID2D1GeometrySink* sink){
for (int i = 2; i < 2 + dataSize * 6; i += 6){
sink->AddBezier(D2D1::BezierSegment(
D2D1::Point2F(dx + (cx + linear(neData[i ], ruData[i ], g))*s,
dy + (cy + linear(neData[i + 1], ruData[i + 1], g))*s),
D2D1::Point2F(dx + (cx + linear(neData[i + 2], ruData[i + 2], g))*s,
dy + (cy + linear(neData[i + 3], ruData[i + 3], g))*s),
D2D1::Point2F(dx + (cx + linear(neData[i + 4], ruData[i + 4], g))*s,
dy + (cy + linear(neData[i + 5], ruData[i + 5], g))*s)));
cx += linear(neData[i + 4], ruData[i + 4], g);
cy += linear(neData[i + 5], ruData[i + 5], g);
}
});
rt->DrawGeometry(geometry.get(), brush.get(), stroke_width);
}
void drawStick(ID2D1HwndRenderTarget* rt, double x, double y, double s, float stroke_width){
double dx = x + (fuPos.x + stick[0])*s;
double dy = y + (fuPos.y + stick[1])*s;
geometry(D2D1::Point2F(dx, dy), [&](ID2D1GeometrySink* sink){
sink->AddBezier(D2D1::BezierSegment(
D2D1::Point2F(dx + stick[2 ]*s,
dy + stick[2 + 1]*s),
D2D1::Point2F(dx + stick[2 + 2]*s,
dy + stick[2 + 3]*s),
D2D1::Point2F(dx + stick[2 + 4]*s,
dy + stick[2 + 5]*s)));
});
rt->DrawGeometry(geometry.get(), brush.get(), stroke_width);
}
struct Ru{
double x, y, tx;
int p;
double grade = 0.;
bool onStick;
will::two_dim::xy<double> stickP = { 0, 0 };
Ru(double x, double y, int p) :x(x), y(y), tx(x), p(p){}
void draw(ID2D1HwndRenderTarget* rt){
brush->SetColor(D2D1::ColorF(0, 0.3f));
rt->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x - 30, y - 13), 80, 20), brush.get(), 0.f);
brush->SetColor(D2D1::ColorF(0));
drawNeru(rt, x, y, 4, grade, 12.f);
if (onStick)
drawStick(rt, x + stickP.x, y + stickP.y, 4, 12.f);
brush->SetColor(D2D1::ColorF((0 + 64 * grade) / 256.f, (64 - 64 * grade) / 256.f, (0 + 64 * grade) / 256.f));
drawNeru(rt, x, y, 4, grade, 6.f);
if (onStick){
brush->SetColor(D2D1::ColorF((64 * grade) / 256.f, (0) / 256.f, (64 * grade) / 256.f));
drawStick(rt, x + stickP.x, y + stickP.y, 4, 6.f);
}
}
void tick(int i){
tx = (p - i) * 140 + w - 385;
x += (tx - x) / 4.0;
if (onStick){
grade += (1 - grade) / 4.0;
stickP.x += (0 - stickP.x) / 4.0;
stickP.y += (0 - stickP.y) / 4.0;
}
}
/*public function mkC(r:int, g : int, b : int) :int{
return r * 65536 + g * 256 + b;
}*/
};
std::vector<Ru> rus;
extern "C"{
void __stdcall construct(ID2D1Factory* factory, ID2D1HwndRenderTarget* rt){
/*tef.defaultTextFormat = new TextFormat("Arial", 30, 0xffffff);
tef.defaultTextFormat.align = "center";
tef.x = w - 135;
tef.y = 300;
tef.width = 100;
tef.height = 100;
tef.text = "Test";
tef.alpha = 0;
addChild(tef);*/
const RECT r = [&]{
RECT r;
GetWindowRect(rt->GetHwnd(), &r);
return r;
}();
w = r.right - r.left;
h = r.bottom - r.top;
//w = 456.f;
//h = 456.f;
stickRu = {42., -30.};
fuPos ={-120. / 2, -75. / 2};
dataSize = 10;
sendRu = 0;
curRu = -5;
pumpPos = 0;
u = 4;
pushed = -1;
next = false;//Ne.Ru
rus.reserve(10);
for (int i = 0; i<10; ++i){
rus.emplace_back(w + 100, h / 2, sendRu);
++sendRu;
}
brush = create_solid_color_brush(rt, D2D1::ColorF(D2D1::ColorF::White));
geometry = create_geometry(factory);
}
void __stdcall run(std::int64_t timer){
::timer = timer;
pumpPos += (0 - pumpPos) / 4.0;
//tef.alpha += (0 - tef.alpha) / 8.0;
while (rus.size()<10){
rus.emplace_back(w + 100, h / 2, sendRu);
++sendRu;
}
if (timer % 30 == 0)
++curRu;
else if (timer % 60 == 15){
pumpPos = h / 12 + h / 3;
u = 0;
}
for (auto it = rus.begin(); it != rus.end(); ++it){
if (it->x < -100){
it = rus.erase(it);
continue;
}
if (u == 3 && !it->onStick){
if (w - 110 < it->x && it->x < w - 100 && pushed != it->p){
it->onStick = true;
it->stickP.x = stickRu.x;
it->stickP.y = stickRu.y;
pushed = it->p;
int cu = std::abs(it->x - (w - 105));
//tef.x = sPos[Math.floor((cu + 1) / 2)];
//tef.text = sName[Math.floor((cu + 1) / 2)];
//tef.alpha = 1;
}
else if (w - 165 < it->x && it->x < 45){
pushed = it->p;
//tef.x = w - 115;
//tef.text = "Bad";
//tef.alpha = 1;
}
}
it->tick(curRu);
}
++u;
}
void __stdcall render(ID2D1HwndRenderTarget* rt){
rt->Clear(D2D1::ColorF(D2D1::ColorF::White));
//spr.graphics.beginFill(0xffffff);
//spr.graphics.drawRect(0, 0, w, h);
brush->SetColor(D2D1::ColorF(0x602f00));
rt->FillRectangle(D2D1::RectF(0.f, h / 2 + 40, w, h / 2 - 40), brush.get());
brush->SetColor(D2D1::ColorF(0x854720));
rt->FillRectangle(D2D1::RectF(0, h / 2 + 50, w, h / 2 - 50), brush.get());
rt->DrawLine(D2D1::Point2F(w - 90, 0), D2D1::Point2F(w - 90, pumpPos + h / 6), brush.get(), 12.f);
brush->SetColor(D2D1::ColorF(0x0));
drawNeru(rt, 100, 100, 2, (std::sin(timer / 4) + 1) / 2 * 1.2, 6.f);
for(auto&& x : rus)
x.draw(rt);
}
void __stdcall destruct(){
geometry.reset();
brush.reset();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment