diff --git a/C++ProjectTemplate.wasm b/C++ProjectTemplate.wasm index a54eea6..215cb71 100755 Binary files a/C++ProjectTemplate.wasm and b/C++ProjectTemplate.wasm differ diff --git a/main.cpp b/main.cpp index 11bc448..2348e97 100644 --- a/main.cpp +++ b/main.cpp @@ -13,6 +13,7 @@ struct Ball{ float radius=0; float mass=0; float simTimeRemaining=0; + bool grounded=false; }; struct Line{ @@ -29,16 +30,19 @@ class MountainClimber : public olc::PixelGameEngine { public: - std::vectorballs; + std::vectorballs; std::vectorlines; Ball*selectedBall; Line*selectedLine; std::vector>collidingPairs; std::vectorfakeBalls; bool selectedLineStart=false; - float friction=0.9f; - float gravity=200.f; - float limit=500.f; + float friction=5.f; + float gravity=2000.f; + float limit=1000.f; + Ball*player; + float moveSpd=250; + float jumpSpd=1000; MountainClimber() { @@ -46,11 +50,10 @@ public: } void AddBall(vf2d pos,float r){ - Ball b; - b.pos=pos; - b.radius=r; - b.mass=r*10; - b.vel.y=rand()%1000-17000; + Ball*b=new Ball(); + b->pos=pos; + b->radius=r; + b->mass=r*10; balls.emplace_back(b); } @@ -67,6 +70,12 @@ public: public: bool OnUserCreate() override { + AddLine({0,360},{640,360},0.1,0); + AddLine({340,360},{640,140},0.1,0); + AddBall({320,300},8); + + ConsoleCaptureStdOut(true); + player=balls[0]; return true; } @@ -79,83 +88,91 @@ public: return fabs((pos1.x - pos2.x)*(pos1.x - pos2.x) + (pos1.y - pos2.y)*(pos1.y - pos2.y)) <= (r1 + r2)*(r1 + r2); }; for(int i=0;isimTimeRemaining=simElapsedTime; } for(int j=0;j0){ - b.originalPos.x=b.pos.x; - b.originalPos.y=b.pos.y; - b.acc.x=-b.vel.x*friction; - b.acc.y=-b.vel.y*friction+gravity; //Gravity constant; - b.vel.x+=b.acc.x*b.simTimeRemaining; - b.vel.y+=b.acc.y*b.simTimeRemaining; - b.pos.x+=b.vel.x*b.simTimeRemaining; - b.pos.y+=b.vel.y*b.simTimeRemaining; + for(Ball*b:balls){ + if(b->simTimeRemaining>0){ + b->originalPos.x=b->pos.x; + b->originalPos.y=b->pos.y; + b->acc.x=-b->vel.x*friction; + b->acc.y=-b->vel.y*friction+((!b->grounded)?gravity:0); //Gravity constant; + b->vel.x+=b->acc.x*b->simTimeRemaining; + b->vel.y+=b->acc.y*b->simTimeRemaining; + b->pos.x+=b->vel.x*b->simTimeRemaining; + b->pos.y+=b->vel.y*b->simTimeRemaining; - if(b.pos.x<0){ - b.pos.x+=ScreenWidth(); + if(b->pos.x<0){ + b->pos.x+=ScreenWidth(); } - if(b.pos.y<0){ - b.pos.y+=ScreenHeight(); + if(b->pos.y<0){ + b->pos.y+=ScreenHeight(); } - if(b.pos.x>=ScreenWidth()){ - b.pos.x-=ScreenWidth(); + if(b->pos.x>=ScreenWidth()){ + b->pos.x-=ScreenWidth(); } - if(b.pos.y>=ScreenHeight()){ - b.pos.y-=ScreenHeight(); + if(b->pos.y>=ScreenHeight()){ + b->pos.y-=ScreenHeight(); } - if(fabs(b.vel.x*b.vel.x+b.vel.y*b.vel.y)vel.x*b->vel.x+b->vel.y*b->vel.y)vel.x=0; + b->vel.y=0; } } } - for(Ball&b:balls){ - float deltaTime=b.simTimeRemaining; + for(Ball*b:balls){ + float deltaTime=b->simTimeRemaining; + bool collisionOccured=false; for(Line&l:lines){ - if(!l.oneWay||l.oneWay&&b.vel.y<0){ + if((!l.oneWay||l.oneWay&&b->vel.y<0)){ vf2d line1={l.endPos.x-l.startPos.x,l.endPos.y-l.startPos.y}; - vf2d line2={b.pos.x-l.startPos.x,b.pos.y-l.startPos.y}; + vf2d line2={b->pos.x-l.startPos.x,b->pos.y-l.startPos.y}; float edgeLength=line1.x*line1.x+line1.y*line1.y; float t=std::max(0.f,std::min(edgeLength,(line1.x*line2.x+line1.y*line2.y)))/edgeLength; vf2d closestPoint={l.startPos.x+t*line1.x,l.startPos.y+t*line1.y}; - float dist=sqrtf((b.pos.x-closestPoint.x)*(b.pos.x-closestPoint.x)+(b.pos.y-closestPoint.y)*(b.pos.y-closestPoint.y)); - if(dist<=b.radius+l.radius){ + float dist=sqrtf((b->pos.x-closestPoint.x)*(b->pos.x-closestPoint.x)+(b->pos.y-closestPoint.y)*(b->pos.y-closestPoint.y)); + if(dist<=b->radius+l.radius){ Ball*fakeBall=new Ball(); fakeBall->radius=l.radius; - fakeBall->mass=b.mass*l.bounceFactor; + fakeBall->mass=b->mass*l.bounceFactor; fakeBall->pos={closestPoint.x,closestPoint.y}; - fakeBall->vel={std::min(limit,std::max(-limit,-b.vel.x)),std::min(limit,std::max(-limit,-b.vel.y))}; + fakeBall->vel={std::min(limit,std::max(-limit,-b->vel.x)),std::min(limit,std::max(-limit,-b->vel.y))}; fakeBalls.push_back(fakeBall); - collidingPairs.push_back({&b,fakeBall}); - float overlap=1.1f*(dist-b.radius-fakeBall->radius); - b.pos.x-=overlap*(b.pos.x-fakeBall->pos.x)/dist; - b.pos.y-=overlap*(b.pos.y-fakeBall->pos.y)/dist; + collidingPairs.push_back({b,fakeBall}); + float overlap=1.1f*(dist-b->radius-fakeBall->radius); + b->pos.x-=overlap*(b->pos.x-fakeBall->pos.x)/dist; + b->pos.y-=overlap*(b->pos.y-fakeBall->pos.y)/dist; + if(b==player&&fakeBall->vel.y<0){//This is an upwards force pushing on us, we have touched ground. + b->grounded=true; + collisionOccured=true; + } } } } - for(Ball&b2:balls){ - if(&b!=&b2){ - if(DoCirclesOverlap(b.pos,b.radius,b2.pos,b2.radius)){ - collidingPairs.push_back({&b,&b2}); - float dist=sqrtf((b.pos.x-b2.pos.x)*(b.pos.x-b2.pos.x)+(b.pos.y-b2.pos.y)*(b.pos.y-b2.pos.y)); - float overlap=0.5f*(dist-b.radius-b2.radius); - b.pos.x-=overlap*(b.pos.x-b2.pos.x)/dist; - b.pos.y-=overlap*(b.pos.y-b2.pos.y)/dist; - b2.pos.x+=overlap*(b.pos.x-b2.pos.x)/dist; - b2.pos.y+=overlap*(b.pos.y-b2.pos.y)/dist; + if(!collisionOccured){ + b->grounded=false; + } + for(Ball*b2:balls){ + if(b!=b2){ + if(DoCirclesOverlap(b->pos,b->radius,b2->pos,b2->radius)){ + collidingPairs.push_back({b,b2}); + float dist=sqrtf((b->pos.x-b2->pos.x)*(b->pos.x-b2->pos.x)+(b->pos.y-b2->pos.y)*(b->pos.y-b2->pos.y)); + float overlap=0.5f*(dist-b->radius-b2->radius); + b->pos.x-=overlap*(b->pos.x-b2->pos.x)/dist; + b->pos.y-=overlap*(b->pos.y-b2->pos.y)/dist; + b2->pos.x+=overlap*(b->pos.x-b2->pos.x)/dist; + b2->pos.y+=overlap*(b->pos.y-b2->pos.y)/dist; } } } - float intendedSpeed=sqrtf(b.vel.x+b.vel.y*b.vel.y); - float intendedDist=intendedSpeed*b.simTimeRemaining; - float actualDist=sqrtf((b.pos.x-b.originalPos.x)*(b.pos.x-b.originalPos.x)+(b.pos.y-b.originalPos.y)*(b.pos.y-b.originalPos.y)); + float intendedSpeed=sqrtf(b->vel.x+b->vel.y*b->vel.y); + float intendedDist=intendedSpeed*b->simTimeRemaining; + float actualDist=sqrtf((b->pos.x-b->originalPos.x)*(b->pos.x-b->originalPos.x)+(b->pos.y-b->originalPos.y)*(b->pos.y-b->originalPos.y)); float actualTime=actualDist/intendedSpeed; - b.simTimeRemaining=b.simTimeRemaining-actualTime; + b->simTimeRemaining=b->simTimeRemaining-actualTime; } float efficiency=1; for(std::pair&pair:collidingPairs){ @@ -188,12 +205,25 @@ public: return fabs((pos.x - point.x)*(pos.x - point.x) + (pos.y - point.y)*(pos.y - point.y)) < (r * r); }; + if(GetKey(A).bHeld){ + player->vel.x=-moveSpd; + player->grounded=false; + } + if(GetKey(D).bHeld){ + player->vel.x=moveSpd; + player->grounded=false; + } + if(GetKey(SPACE).bPressed){ + player->vel.y=-jumpSpd; + player->grounded=false; + } + if (GetMouse(0).bPressed){ selectedBall = nullptr; - for (Ball&b:balls){ - if (IsPointInCircle(b.pos,b.radius,GetMousePos())) + for (Ball*b:balls){ + if (IsPointInCircle(b->pos,b->radius,GetMousePos())) { - selectedBall = &b; + selectedBall = b; break; } } @@ -233,9 +263,9 @@ public: selectedLine=nullptr; } if(GetMouse(1).bHeld){ - for(Ball&b:balls){ - b.vel.x+=(GetMouseX()-b.pos.x)*0.01f; - b.vel.y+=(GetMouseY()-b.pos.y)*0.01f; + for(Ball*b:balls){ + b->vel.x+=(GetMouseX()-b->pos.x)*0.01f; + b->vel.y+=(GetMouseY()-b->pos.y)*0.01f; } } @@ -245,17 +275,13 @@ public: Clear(BLACK); - if(GetKey(SPACE).bPressed){ - AddBall({610,620},rand()%4+8); - } - HandlePhysics(fElapsedTime); - for(Ball&b:balls){ - if(selectedBall==&b){ - FillCircle(b.pos,b.radius,YELLOW); + for(Ball*b:balls){ + if(selectedBall==b){ + FillCircle(b->pos,b->radius,YELLOW); } else { - FillCircle(b.pos,b.radius); + FillCircle(b->pos,b->radius); } } for(Line&l:lines){ diff --git a/vel.x=-100 b/vel.x=-100 new file mode 100644 index 0000000..e69de29