Browse Source

working at angry birds

vlod 1 year ago
parent
commit
715b3323e5

+ 0 - 0
Pika/core/pikaSTD/engineLibraresSupport/ph2d/engineph2dSupport.cpp


+ 18 - 0
Pika/core/pikaSTD/engineLibraresSupport/ph2d/engineph2dSupport.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include <gl2d/gl2d.h>
+#include <baseContainer.h>
+
+
+
+namespace pika
+{
+
+	namespace ph2d
+	{
+
+
+
+	}
+
+}

+ 3 - 0
Pika/gameplay/containers.h

@@ -44,6 +44,8 @@ Container *getContainer(const char* name, pika::memory::MemoryArena *memoryArena
 
 #include "containers/physicsTest/physicsTest.h"
 
+#include "containers/angryBirds/angryBirds.h"
+
 #if PIKA_PRODUCTION == 1
 
 #define PIKA_ALL_CONTAINERS() \
@@ -55,6 +57,7 @@ Container *getContainer(const char* name, pika::memory::MemoryArena *memoryArena
 
 #define PIKA_ALL_CONTAINERS() \
 	PIKA_DECLARE_CONTAINER(Gameplay) \
+	PIKA_DECLARE_CONTAINER(AngryBirds) \
 	PIKA_DECLARE_CONTAINER(SushiViewer) \
 	PIKA_DECLARE_CONTAINER(ImmageViewer) \
 	PIKA_DECLARE_CONTAINER(ThreeDTest) \

+ 300 - 0
Pika/gameplay/containers/angryBirds/angryBirds.h

@@ -0,0 +1,300 @@
+#pragma once
+
+#include <gl2d/gl2d.h>
+#include <imgui.h>
+#include <baseContainer.h>
+#include <shortcutApi/shortcutApi.h>
+#include <pikaSizes.h>
+#include <imgui_spinner.h>
+#include "ph2d/ph2d.h"
+#include <engineLibraresSupport/engineGL2DSupport.h>
+
+
+struct AngryBirds: public Container
+{
+
+	enum blockTypes
+	{
+		woodBalls,
+		woodSmall,
+		stoneplank,
+		glassplank,
+		woodplank,
+		glassblock,
+		woodblock,
+		stoneblock,
+	};
+
+	glm::ivec2 sizes[8]{
+		glm::ivec2{40,40},
+		glm::ivec2{40,40},
+
+		glm::ivec2(204, 20),
+		glm::ivec2(204, 20),
+		glm::ivec2(204, 20),
+
+		glm::ivec2(80,80),
+		glm::ivec2(80,80),
+		glm::ivec2(80,80),
+	};
+
+	const char *textureNames[8]
+	{
+		PIKA_RESOURCES_PATH "sus/woodballs.png",
+		PIKA_RESOURCES_PATH "sus/woodsmall.png",
+		PIKA_RESOURCES_PATH "sus/stoneplank.png",
+		PIKA_RESOURCES_PATH "sus/glassplank.png",
+		PIKA_RESOURCES_PATH "sus/woodplank.png",
+		PIKA_RESOURCES_PATH "sus/glass.png",
+		PIKA_RESOURCES_PATH "sus/wood.png",
+		PIKA_RESOURCES_PATH "sus/stone.png",
+	};
+
+	gl2d::Texture textures[8];
+	gl2d::TextureAtlas texturesAtlas[8];
+
+	gl2d::Renderer2D renderer;
+	ph2d::PhysicsEngine physicsEngine;
+
+	struct GameBlock
+	{
+		int textureType = 0;
+		int materialType = 0;
+	};
+
+	std::unordered_map<ph2d::ph2dBodyId, GameBlock> gameBlocks;
+
+	void addBlock(int type, glm::vec2 pos)
+	{
+		glm::ivec2 size = sizes[type];
+
+		if (type == woodBalls)
+		{
+			auto body = physicsEngine.addBody(pos,
+				ph2d::createCircleCollider(size.x/2));
+
+			GameBlock b;
+			b.textureType = type;
+			gameBlocks.emplace(body, b);
+		}
+		else
+		{
+			auto body = physicsEngine.addBody(pos,
+				ph2d::createBoxCollider(size));
+
+			GameBlock b;
+			b.textureType = type;
+			gameBlocks.emplace(body, b);
+		}
+
+	}
+
+	//todo user can request imgui ids; shortcut manager context; allocators
+	static ContainerStaticInfo containerInfo()
+	{
+		ContainerStaticInfo info = {};
+		info.defaultHeapMemorySize = pika::MB(10);
+		info.requestImguiFbo = true;
+		info.pushAnImguiIdForMe = true;
+		info.andInputWithWindowHasFocus = 0;
+		info.andInputWithWindowHasFocusLastFrame = 0;
+
+		return info;
+	}
+
+
+	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
+	{
+		renderer.create(requestedInfo.requestedFBO.fbo);
+
+		for (int i = 0; i < 8; i++)
+		{
+			textures[i] = pika::gl2d::loadTexture(textureNames[i], requestedInfo);
+			texturesAtlas[i] = gl2d::TextureAtlas(3, 1);
+		}
+
+		physicsEngine.simulationphysicsSettings.gravity = glm::vec2(0, 9.81) * 100.f;
+
+
+		//for (int i = 0; i < 10; i++)
+		//{
+		//	if (1)
+		//	{
+		//		float w = rand() % 100 + 20;
+		//		float h = rand() % 100 + 20;
+		//
+		//		auto body = physicsEngine.addBody({rand() % 800 + 100, rand() % 800 + 100},
+		//			ph2d::createBoxCollider({w, h}));
+		//		physicsEngine.bodies[body].motionState.rotation = ((rand() % 800) / 800.f) * 3.14159f;
+		//	}
+		//
+		//	for (int j = 0; j < 1; j++)
+		//	{
+		//		float r = rand() % 35 + 10;
+		//
+		//		physicsEngine.addBody({rand() % 800 + 100, rand() % 800 + 100},
+		//			ph2d::createCircleCollider({r}));
+		//	}
+		//}
+
+		//floor
+		physicsEngine.addHalfSpaceStaticObject({0, 800}, {0.0, 1});
+
+		return true;
+	}
+
+	bool update(pika::Input input, pika::WindowState windowState,
+		RequestedContainerInfo &requestedInfo)
+	{
+	#pragma region init stuff
+		int w = 0; int h = 0;
+		w = windowState.frameBufferW; //window w
+		h = windowState.frameBufferH; //window h
+		glClear(GL_COLOR_BUFFER_BIT); //clear screen
+		renderer.updateWindowMetrics(w, h);
+	#pragma endregion
+
+	#pragma region update simulation
+
+		physicsEngine.runSimulation(input.deltaTime);
+
+	#pragma endregion
+
+		pika::gl2d::cameraController(renderer.currentCamera, input, 100, 1);
+
+
+		glm::vec2 mousePosScreen = {input.mouseX, input.mouseY};
+		glm::vec2 mousePosWorld = {0, 0};
+
+	#pragma region get cursor position
+		auto viewRect = renderer.getViewRect();
+
+		auto lerp = [](auto a, auto b, auto c)
+		{
+			return a * (1.f - c) + b * c;
+		};
+
+		mousePosWorld = lerp(glm::vec2(viewRect.x, viewRect.y),
+			glm::vec2(viewRect.x + viewRect.z, viewRect.y + viewRect.w),
+			glm::vec2(input.mouseX, input.mouseY) / glm::vec2(windowState.windowW, windowState.windowH));
+	#pragma endregion
+
+		if (input.lMouse.pressed())
+		{
+			addBlock(1, mousePosWorld);
+		}
+
+
+	#pragma region render
+
+		for (auto &index : physicsEngine.bodies)
+		{
+			auto &b = index.second;
+
+			auto itFound = gameBlocks.find(index.first);
+
+			if (itFound != gameBlocks.end())
+			{
+				int textureIndex = itFound->second.textureType;
+
+				//renderer.renderRectangle(b.getAABB().asVec4(),
+				//	textures[textureIndex],
+				//	Colors_White,
+				//	{}, b.motionState.rotation, texturesAtlas[textureIndex].get(0, 0));
+
+			}
+
+			
+		}
+
+	#pragma endregion
+
+
+	#pragma region render debug
+
+		for (auto &index : physicsEngine.bodies)
+		{
+			auto &b = index.second;
+
+			auto color = Colors_White;
+
+			if (b.intersectPoint(mousePosWorld))
+			{
+				color = Colors_Turqoise;
+			}
+		
+			//if (OBBvsPoint(physicsEngine.bodies[i].getAABB(),
+			//	physicsEngine.bodies[i].motionState.rotation,
+			//	{input.mouseX, input.mouseY}))
+			//{
+			//	color = Colors_Blue;
+			//}
+
+			if (b.collider.type == ph2d::ColliderCircle)
+			{
+				renderer.renderCircleOutline(b.motionState.pos,
+					b.collider.collider.circle.radius, color, 2, 32);
+
+				glm::vec2 vector = {1,0};
+				vector = ph2d::rotateAroundCenter(vector, b.motionState.rotation);
+				renderer.renderLine(b.motionState.pos, b.motionState.pos + vector *
+					b.collider.collider.circle.radius, color, 4);
+
+			}
+			else if (b.collider.type == ph2d::ColliderBox)
+			{
+				float rotation = glm::degrees(b.motionState.rotation);
+
+				renderer.renderRectangleOutline(b.getAABB().asVec4(), color, 2, {}, rotation);
+			}
+			else if (b.collider.type == ph2d::ColliderHalfSpace)
+			{
+
+				ph2d::LineEquation lineEquation;
+				lineEquation.createFromRotationAndPoint(b.motionState.rotation,
+					b.motionState.pos);
+
+				glm::vec2 lineEquationStart = lineEquation.getClosestPointToOrigin();
+				lineEquationStart -= lineEquation.getLineVector() * 1000.f;
+				renderer.renderLine(lineEquationStart, lineEquationStart + lineEquation.getLineVector() * 2000.f, Colors_Red);
+			}
+			else if (b.collider.type == ph2d::ColliderConvexPolygon)
+			{
+				auto &c = b.collider.collider.convexPolygon;
+
+				for (int i = 0; i < c.vertexCount; i++)
+				{
+					glm::vec2 p1 = c.vertexesObjectSpace[i] + b.motionState.pos;
+					glm::vec2 p2 = c.vertexesObjectSpace[(i + 1) % c.vertexCount] + b.motionState.pos;
+
+					p1 = ph2d::rotateAroundPoint(p1, b.motionState.pos, b.motionState.rotation);
+					p2 = ph2d::rotateAroundPoint(p2, b.motionState.pos, b.motionState.rotation);
+
+					renderer.renderLine(p1, p2, color);
+				}
+
+			}
+
+		}
+
+		renderer.renderRectangle({mousePosWorld - glm::vec2(3,3), 6, 6}, Colors_Red);
+
+	#pragma endregion
+
+
+
+
+		renderer.flush();
+
+
+		return true;
+	}
+
+	//optional
+	void destruct(RequestedContainerInfo &requestedInfo)
+	{
+
+	}
+
+};
+

+ 10 - 9
Pika/gameplay/containers/physicsTest/physicsTest.h

@@ -43,17 +43,17 @@ struct PhysicsTest: public Container
 		{
 			//if (i == 1) { mass = 0; }
 
-			if (0)
+			if (1)
 			{
 				float w = rand() % 100 + 20;
 				float h = rand() % 100 + 20;
 
-				physicsEngine.addBody({rand() % 800 + 100, rand() % 800 + 100},
+				auto body = physicsEngine.addBody({rand() % 800 + 100, rand() % 800 + 100},
 					ph2d::createBoxCollider({w, h}));
-				physicsEngine.bodies.back().motionState.rotation = ((rand() % 800) / 800.f) * 3.14159f;
+				physicsEngine.bodies[body].motionState.rotation = ((rand() % 800) / 800.f) * 3.14159f;
 			}
 
-			for (int j = 0; j < 2; j++)
+			for (int j = 0; j < 1; j++)
 			{
 				float r = rand() % 35 + 10;
 
@@ -73,13 +73,12 @@ struct PhysicsTest: public Container
 		};
 		//physicsEngine.addBody({500, 200}, ph2d::createConvexPolygonCollider(shape, 5));
 
-
 		//physicsEngine.addBody({500, 1100}, 
 		//	ph2d::createBoxCollider({1100, 10}));
 
-		physicsEngine.addBody({500, 500}, ph2d::createBoxCollider({400, 50}));
-		//physicsEngine.bodies.back().flags.setFreezePosition();
-		physicsEngine.bodies.back().flags.setFreezeRotation();
+		auto body = physicsEngine.addBody({500, 500}, ph2d::createBoxCollider({400, 50}));
+		physicsEngine.bodies[body].flags.setFreezePosition();
+		//physicsEngine.bodies[body].flags.setFreezeRotation();
 
 		//physicsEngine.addBody({1, 800}, ph2d::createBoxCollider({800, 50}));
 		//physicsEngine.bodies[1].motionState.mass = 0;
@@ -258,8 +257,10 @@ struct PhysicsTest: public Container
 				physicsEngine.runSimulation(0);
 			}
 
-			for (auto &b : physicsEngine.bodies)
+			for (auto &it : physicsEngine.bodies)
 			{
+				auto &b = it.second;
+
 				auto bottom = b.getAABB().max().y;
 				auto left = b.getAABB().min().x;
 				auto right = b.getAABB().max().x;

+ 0 - 4
Pika/gameplay/containers/pikaGameplay.h

@@ -66,8 +66,6 @@ struct Gameplay : public Container
 
 
 
-
-
 		if (input.buttons[pika::Button::A].released())
 		{
 			//.. A button was released
@@ -76,8 +74,6 @@ struct Gameplay : public Container
 
 
 
-
-
 		glClear(GL_COLOR_BUFFER_BIT);
 
 		if (pika::shortcut(input, "Ctrl + S"))

+ 2 - 2
Pika/resources/logs.txt

@@ -1,2 +1,2 @@
-#2024-11-22 18:47:46: Created container: PhysicsTest
-#2024-11-22 18:47:49: Destroyed continer: PhysicsTest #1
+#2024-11-22 23:05:30: Created container: AngryBirds
+#2024-11-22 23:05:33: Destroyed continer: AngryBirds #1

BIN
Pika/resources/sus/blue.png


BIN
Pika/resources/sus/glass.png


BIN
Pika/resources/sus/glassplank.png


BIN
Pika/resources/sus/pig.png


BIN
Pika/resources/sus/red.png


BIN
Pika/resources/sus/stone.png


BIN
Pika/resources/sus/stoneplank.png


BIN
Pika/resources/sus/wood.png


BIN
Pika/resources/sus/woodballs.png


BIN
Pika/resources/sus/woodplank.png


BIN
Pika/resources/sus/woodsmall.png


BIN
Pika/resources/sus/yellow.png


+ 9 - 6
Pika/thirdparty/ph2d/include/ph2d/ph2d.h

@@ -22,6 +22,7 @@
 #include <glm/glm.hpp>
 #include <vector>
 #include <bitset>
+#include <unordered_map>
 
 constexpr static int PH2D_MAX_CONVEX_SHAPE_POINTS = 12;
 
@@ -300,7 +301,6 @@ namespace ph2d
 		Collider collider = {};
 		
 		ph2dUserData userData;
-		ph2dBodyId id = 0;
 
 		//we use center position
 		MotionState motionState;
@@ -339,8 +339,10 @@ namespace ph2d
 		glm::vec2 tangentA = {};
 		glm::vec2 tangentB = {};
 		float penetration = 0;
-		unsigned short A = 0;
-		unsigned short B = 0;
+		ph2dBodyId A = 0;
+		ph2dBodyId B = 0;
+		float massA = 0;
+		float massB = 0;
 	};
 
 	struct SimulationPhysicsSettings
@@ -360,8 +362,9 @@ namespace ph2d
 	{
 		ph2dBodyId idCounter = 0;
 
-		std::vector<Body> bodies;
+		std::unordered_map<ph2dBodyId, Body> bodies;
 
+		//for internal use for now
 		std::vector<ManifoldIntersection> intersections;
 
 		//this will make the simulation run at fixed intervals of time, making it deterministic.
@@ -377,9 +380,9 @@ namespace ph2d
 
 		SimulationPhysicsSettings simulationphysicsSettings;
 
-		void addBody(glm::vec2 centerPos, Collider collider);
+		ph2dBodyId addBody(glm::vec2 centerPos, Collider collider);
 
-		void addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal);
+		ph2dBodyId addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal);
 	};
 
 	glm::mat2 rotationMatrix(float angle);

+ 46 - 37
Pika/thirdparty/ph2d/src/ph2d.cpp

@@ -1089,6 +1089,7 @@ namespace ph2d
 			return ph2d::HalfSpaceVsOBB(
 				lineEquation, abox, A.motionState.rotation, penetration, normal, contactPoint,
 			tangentB, tangentA);
+
 		}
 
 
@@ -1682,45 +1683,51 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 		};
 
 
-		//gravity
-		for (int i = 0; i < bodies.size(); i++)
+		for (auto &it : bodies)
 		{
+			auto &b = it.second;
+
+			//gravity
 			//no need to check for freeze position on x y because I clear them later anyway.
-			if (bodies[i].motionState.mass != 0 && bodies[i].motionState.mass != INFINITY
-				&& !bodies[i].flags.isFreezePosition()
+			if (b.motionState.mass != 0 && b.motionState.mass != INFINITY
+				&& !b.flags.isFreezePosition()
 				)
 			{
-				bodies[i].motionState.acceleration += simulationphysicsSettings.gravity
-					* bodies[i].gravityScale;
+				b.motionState.acceleration += simulationphysicsSettings.gravity
+					* b.gravityScale;
 			}
-		}
 
-		size_t bodiesSize = bodies.size();
-		for (int i = 0; i < bodiesSize; i++)
-		{
-			if (bodies[i].motionState.mass == 0)
+			//make sure all objects use a valid mass
+			if (b.motionState.mass <= 0)
 			{
-				bodies[i].motionState.mass = INFINITY;
+				b.motionState.mass = INFINITY;
 			}
 
-			applyDrag(bodies[i].motionState, bodies[i].dragScale, simulationphysicsSettings);
-			applyAngularDrag(bodies[i].motionState, bodies[i].angularDragScale, simulationphysicsSettings);
-		};
+			if (b.motionState.momentOfInertia <= 0)
+			{
+				b.motionState.momentOfInertia = INFINITY;
+			}
+
+			applyDrag(b.motionState, b.dragScale, simulationphysicsSettings);
+			applyAngularDrag(b.motionState, b.angularDragScale, simulationphysicsSettings);
+
+		}
+
 
 		for (int _ = 0; _ < collisionChecksCount; _++)
 		{
 			intersections.clear();
 
-			for (int i = 0; i < bodiesSize; i++)
+			for (auto &it1 : bodies)
 			{
 				//detect colisions
-				for (int j = 0; j < bodiesSize; j++)
+				for (auto &it2 : bodies)
 				{
 					//break;
-					if (i == j) { break; }
+					if (it1.first == it2.first) { break; }
 
-					auto &A = bodies[i];
-					auto &B = bodies[j];
+					auto &A = it1.second;
+					auto &B = it2.second;
 
 					glm::vec2 normal = {};
 					glm::vec2 contactPoint = {};
@@ -1734,13 +1741,15 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 					{
 						ManifoldIntersection intersection = {};
 
-						intersection.A = i;
-						intersection.B = j;
+						intersection.A = it1.first;
+						intersection.B = it2.first;
 						intersection.tangentA = tangentA;
 						intersection.tangentB = tangentB;
 						intersection.contactPoint = contactPoint;
 						intersection.normal = normal;
 						intersection.penetration = penetration;
+						intersection.massA = A.motionState.mass;
+						intersection.massB = B.motionState.mass;
 
 						intersections.push_back(intersection);
 					}
@@ -1752,13 +1761,14 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 			std::sort(intersections.begin(), intersections.end(), [&](auto &a, auto &b)
 			{
 				// Retrieve the mass of the objects from the indices A and B
-				float massA = bodies[a.A].motionState.mass;
-				float massB = bodies[a.B].motionState.mass;
+				float massA = a.massA;
+				float massB = a.massB;
 
 				// Sort first by penetration depth (deeper penetration first)
 				if (a.penetration != b.penetration)
 					return a.penetration > b.penetration;  // Sort by deeper penetration first
 
+				//TODO this aint right!
 				// If penetrations are equal, sort by mass (lighter mass first)
 				return massA < massB;  // Lighter mass first (this avoids smaller objects being "swallowed")
 			});
@@ -1791,11 +1801,13 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 
 		}
 		
-		for (int i = 0; i < bodiesSize; i++)
+		for (auto &it : bodies)
 		{
-			integrateForces(bodies[i].motionState, deltaTime, simulationphysicsSettings, 
-				bodies[i].flags);
-			bodies[i].motionState.lastPos = bodies[i].motionState.pos;
+			auto &b = it.second;
+
+			integrateForces(b.motionState, deltaTime, simulationphysicsSettings, 
+				b.flags);
+			b.motionState.lastPos = b.motionState.pos;
 		};
 	
 
@@ -1804,18 +1816,16 @@ void ph2d::PhysicsEngine::runSimulation(float deltaTime)
 }
 
 
-void ph2d::PhysicsEngine::addBody(glm::vec2 centerPos, Collider collider)
+ph2d::ph2dBodyId ph2d::PhysicsEngine::addBody(glm::vec2 centerPos, Collider collider)
 {
-
 	Body body;
-	body.id = ++idCounter;
 	body.motionState.setPos(centerPos);
 	body.collider = collider;
 	body.motionState.mass = collider.computeMass();
 	body.motionState.momentOfInertia = collider.computeMomentOfInertia(body.motionState.mass);
 
-	bodies.push_back(body);
-
+	bodies.emplace(++idCounter, body);
+	return idCounter;
 }
 
 
@@ -1842,18 +1852,17 @@ glm::vec2 ph2d::rotationToVector(float rotation)
 	return glm::normalize(glm::vec2(-x, y));
 }
 
-void ph2d::PhysicsEngine::addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal)
+ph2d::ph2dBodyId ph2d::PhysicsEngine::addHalfSpaceStaticObject(glm::vec2 position, glm::vec2 normal)
 {
 	Body body;
-	body.id = ++idCounter;
 	body.motionState.setPos(position);
 	body.collider.type = ColliderType::ColliderHalfSpace;
 	body.motionState.mass = 0;
 	body.motionState.momentOfInertia = 0;
 
 	body.motionState.rotation = vectorToRotation(normal);
-	bodies.push_back(body);
-
+	bodies.emplace(++idCounter ,body);
+	return idCounter;
 }