Object collisions implemented.

This commit is contained in:
sigonasr2 2025-08-31 03:07:00 -05:00
parent b866a4e91c
commit dbf6e45da5
7 changed files with 83 additions and 10 deletions

View File

@ -40,6 +40,20 @@
"building1"
],
"valuesAsFlags": false
},
{
"color": "#ffff55ff",
"drawFill": true,
"id": 3,
"members": [
],
"name": "PlayerSpawn",
"type": "class",
"useAs": [
"property",
"object",
"project"
]
}
]
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="41" height="37" tilewidth="16" tileheight="16" infinite="0" nextlayerid="8" nextobjectid="2">
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="41" height="37" tilewidth="16" tileheight="16" infinite="0" nextlayerid="8" nextobjectid="4">
<tileset firstgid="1" source="Village.tsx"/>
<tileset firstgid="1025" source="Collision.tsx"/>
<tileset firstgid="1026" source="Field Tiles.tsx"/>
@ -208,11 +208,14 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<objectgroup id="4" name="Object Layer 1" visible="0">
<objectgroup id="4" name="Object Layer 1">
<object id="1" type="Building" x="160" y="128" width="128" height="96">
<properties>
<property name="Building Type" propertytype="Buildings" value="building1"/>
</properties>
</object>
<object id="2" name="Player Spawn" type="PlayerSpawn" x="220" y="248">
<point/>
</object>
</objectgroup>
</map>

View File

@ -39,6 +39,7 @@ All rights reserved.
#include "ShepGame.h"
#include "GameObject.h"
#include "GameSettings.h"
#include <ranges>
GameObject::GameObject(const vf3d&pos,const vf3d&scale,const ObjectID&id,const std::string&spriteMeshName,const MeshType&type)
:pos(pos),scale(scale),id(id),spriteMeshName(spriteMeshName),type(type){};
@ -134,4 +135,9 @@ void GameObject::ApplyCharacterAnimation(const uint8_t animInd,const SkinTone to
animState.AddState(state,animations.at(state));
}
anim=Animate2D::AnimationState{};
}
void GameObject::SetPos(const vf2d&pos){
this->pos.x=pos.x;
this->pos.z=pos.y;
}

View File

@ -59,6 +59,7 @@ public:
const Renderable&GetSprite()const;
void SetAutoScale(const vf2d&unitDivision); //Takes the texture width/height and divides it by unitDivion then scales the Game Object accordingly. Useful for scaling tilemaps.
void ApplyCharacterAnimation(const uint8_t animInd,const SkinTone tone);
void SetPos(const vf2d&pos);
struct Player{
static void Update(GameObject&self,const float&fElapsedTime);

View File

@ -42,19 +42,31 @@ All rights reserved.
void GameObject::Player::Update(GameObject&self,const float&fElapsedTime){
ShepGame&game{ShepGame::Game()};
if(game.GetKey(Key::W).bHeld){
self.pos.z-=fElapsedTime*GameSettings::PLAYER_SPD;
vf2d moveToCoord{self.pos.xz()+vf2d{0.f,-fElapsedTime*GameSettings::PLAYER_SPD}};
ShepGame::GetAdjustedMovePos(self,moveToCoord);
self.pos.x=moveToCoord.x;
self.pos.z=moveToCoord.y;
if(self.anim)self.animState.ChangeState(*self.anim,AnimationState::WALK_N);
}
if(game.GetKey(Key::A).bHeld){
self.pos.x-=fElapsedTime*GameSettings::PLAYER_SPD;
vf2d moveToCoord{self.pos.xz()+vf2d{-fElapsedTime*GameSettings::PLAYER_SPD,0.f}};
ShepGame::GetAdjustedMovePos(self,moveToCoord);
self.pos.x=moveToCoord.x;
self.pos.z=moveToCoord.y;
if(self.anim)self.animState.ChangeState(*self.anim,AnimationState::WALK_W);
}
if(game.GetKey(Key::S).bHeld){
self.pos.z+=fElapsedTime*GameSettings::PLAYER_SPD;
vf2d moveToCoord{self.pos.xz()+vf2d{0.f,fElapsedTime*GameSettings::PLAYER_SPD}};
ShepGame::GetAdjustedMovePos(self,moveToCoord);
self.pos.x=moveToCoord.x;
self.pos.z=moveToCoord.y;
if(self.anim)self.animState.ChangeState(*self.anim,AnimationState::WALK_S);
}
if(game.GetKey(Key::D).bHeld){
self.pos.x+=fElapsedTime*GameSettings::PLAYER_SPD;
vf2d moveToCoord{self.pos.xz()+vf2d{fElapsedTime*GameSettings::PLAYER_SPD,0.f}};
ShepGame::GetAdjustedMovePos(self,moveToCoord);
self.pos.x=moveToCoord.x;
self.pos.z=moveToCoord.y;
if(self.anim)self.animState.ChangeState(*self.anim,AnimationState::WALK_E);
}
if(game.GetKey(Key::W).bReleased){

View File

@ -105,9 +105,6 @@ bool ShepGame::OnUserCreate(){
LoadMap("Town1.tmx");
auto&player{AddGameObject({0,0,0},{1,2,1},GameObject::ObjectID::PLAYER,"nico-trapper.png",MeshType::SPRITE)};
player.ApplyCharacterAnimation(29,SkinTone::TONE_2);
AddGameObject({9,0,10},{1,2,1},GameObject::ObjectID::DEFAULT,"nico-trapper.png",MeshType::SPRITE).ApplyCharacterAnimation(32,SkinTone::TONE_3);
AddLight({{4,0,10},WHITE});
@ -124,6 +121,10 @@ void ShepGame::LoadMap(const std::string&filename){
collisionTiles.clear();
objects.clear();
lights.clear();
auto&player{AddGameObject({0,0,0},{1,2,1},GameObject::ObjectID::PLAYER,"nico-trapper.png",MeshType::SPRITE)};
player.ApplyCharacterAnimation(29,SkinTone::TONE_2);
TMXParser map{"assets/maps/"+filename};
std::vector<std::vector<int32_t>>tiles{map.GetData().GetLayers()[map.GetData().GetLayers().size()-1].tiles};
for(int y:std::ranges::iota_view(size_t(0),tiles.size())){
@ -151,6 +152,15 @@ void ShepGame::LoadMap(const std::string&filename){
}
}
}
if(map.GetData().ZoneData.count("PlayerSpawn")>0){
const std::vector<ZoneData>&zones{map.GetData().ZoneData.at("PlayerSpawn")};
for(const ZoneData&zone:zones){
geom2d::rect<int>spawnZone{zone.zone};
for(GameObject&obj:objects|std::views::filter([](const GameObject&obj){return obj.GetID()==GameObject::ObjectID::PLAYER;})){
obj.SetPos(spawnZone.pos/map.GetData().GetMapData().TileSize);
}
}
}
if(map.GetData().ZoneData.count("Building")>0){
const std::vector<ZoneData>&zones{map.GetData().ZoneData.at("Building")};
for(const ZoneData&zone:zones){
@ -201,6 +211,8 @@ void ShepGame::LoadAnimations(){
}
bool ShepGame::OnUserUpdate(float fElapsedTime){
fElapsedTime=std::min(0.1f,fElapsedTime);
using namespace olc;
if(GameSettings::DEBUG_CAMERA){
@ -307,6 +319,28 @@ const bool ShepGame::GetInputReleased(const Action&action){
return false;
}
void ShepGame::GetAdjustedMovePos(const GameObject&obj,vf2d&movePos){
for(const auto&collisionObj:game->objects){
if(&obj==&collisionObj
||collisionObj.GetMeshType()==MeshType::FLOOR
||collisionObj.GetMeshType()==MeshType::OBJ)continue;
const auto&objRadius{obj.GetScale().x};
geom2d::rect<float>collisionRect{collisionObj.GetPos().xz(),collisionObj.GetScale().xz()/2};
geom2d::rect<float>projRect{collisionObj.GetPos().xz()-vf2d{objRadius,objRadius}*2,collisionObj.GetScale().xz()/2+vf2d{objRadius,objRadius}*4};
geom2d::circle<float>circ{obj.GetPos().xz(),objRadius};
if(geom2d::contains(collisionRect,circ)||geom2d::overlaps(collisionRect,circ)){
const auto&projCircle{geom2d::project(circ,projRect,geom2d::ray<float>{projRect.middle(),circ.pos-projRect.middle()})};
if(projCircle){
movePos=*projCircle;
}else{
std::cout<<"WARNING! Something went terribly wrong trying to project a collision! THIS SHOULD NOT BE HAPPENING!"<<std::endl;
throw;
}
}
}
}
ShepGame&ShepGame::Game(){
if(game==nullptr){
std::cout<<"WARNING! Trying to reference Game pointer before game has been initialized! THIS IS NOT ALLOWED!"<<std::endl;;
@ -321,4 +355,5 @@ int main()
if (shep.Construct(1280, 720, 1, 1, false, false))
shep.Start();
return 0;
}
}

View File

@ -63,6 +63,8 @@ public:
const bool GetInput(const Action&actionName);
const bool GetInputPressed(const Action&actionName);
const bool GetInputReleased(const Action&actionName);
static void GetAdjustedMovePos(const GameObject&obj,vf2d&movePos);
private:
static ShepGame*game;