mirror of
https://github.com/sigonasr2/hamster.git
synced 2025-04-19 23:09:40 -05:00
Add NPCAI class containing NPCAI file formats and storage for AI paths along with recording AIs.
This commit is contained in:
parent
12432dd61a
commit
337b9ecc07
1
TestLevel.tmx.0
Normal file
1
TestLevel.tmx.0
Normal file
@ -0,0 +1 @@
|
|||||||
|
97 384 0 97 400 0 97 416 0 97 432 0 97 448 0 102 464 0 112 473 0 115 480 0 115 496 0 115 512 0 111 526 0 110 528 0 95 543 0 95 544 0 89 560 0 90 576 0 96 587 0 101 592 0 109 608 0 109 624 0 109 640 0 109 656 0 109 672 0 109 688 0 109 691 1 112 701 0 114 704 0 128 718 0 130 720 0 144 733 0 146 736 0 160 750 0 163 752 0 176 754 0 192 753 0 194 751 0 208 738 0 211 735 0 224 723 0 227 719 0 240 704 0 240 703 0 243 687 0 243 671 0 243 655 0 243 639 0 243 623 0 243 607 0 243 591 0 243 575 0 243 559 0 243 543 0 243 527 0 243 511 0 247 495 0 256 484 0 261 479 0 272 468 0 277 463 0 288 454 0 304 451 0 308 448 1 309 447 0 312 431 0 303 421 0 298 415 0 287 405 0 283 400 1 282 399 0 271 388 0 265 383 0 255 372 0 250 367 0 239 356 0 233 351 0 223 340 0 218 335 0 207 328 0 190 327 0 174 327 0 159 327 0 144 319 0 143 318 0 128 303 0 127 302 0 112 287 0 111 287 0 95 281 0 79 281 0 63 281 0 47 278 0 40 271 0 31 261 0 29 255 0 28 239 0 28 223 0 28 206 0 32 198 0 37 191 0 48 182 0 64 177 0 80 178 0 96 188 0 99 192 0 112 200 0 128 201 0 144 201 0 161 201 0 176 201 0 192 201 0 209 201 0 224 201 0
|
1
TestLevel.tmx.1
Normal file
1
TestLevel.tmx.1
Normal file
@ -0,0 +1 @@
|
|||||||
|
97 384 0 97 400 0 97 416 0 97 432 0 97 448 0 102 464 0 112 473 0 115 480 0 115 496 0 115 512 0 111 526 0 110 528 0 95 543 0 95 544 0 89 560 0 90 576 0 96 587 0 101 592 0 109 608 0 109 624 0 109 640 0 109 656 0 109 672 0 109 688 0 109 691 1 112 701 0 114 704 0 128 718 0 130 720 0 144 733 0 146 736 0 160 750 0 163 752 0 176 754 0 192 753 0 194 751 0 208 738 0 211 735 0 224 723 0 227 719 0 240 704 0 240 703 0 243 687 0 243 671 0 243 655 0 243 639 0 243 623 0 243 607 0 243 591 0 243 575 0 243 559 0 243 543 0 243 527 0 243 511 0 247 495 0 256 484 0 261 479 0 272 468 0 277 463 0 288 454 0 304 451 0 308 448 1 309 447 0 312 431 0 303 421 0 298 415 0 287 405 0 283 400 1 282 399 0 271 388 0 265 383 0 255 372 0 250 367 0 239 356 0 233 351 0 223 340 0 218 335 0 207 328 0 190 327 0 174 327 0 159 327 0 144 319 0 143 318 0 128 303 0 127 302 0 112 287 0 111 287 0 95 281 0 79 281 0 63 281 0 47 278 0 40 271 0 31 261 0 29 255 0 28 239 0 28 223 0 28 206 0 32 198 0 37 191 0 48 182 0 64 177 0 80 178 0 96 188 0 99 192 0 112 200 0 128 201 0 144 201 0 161 201 0 176 201 0 192 201 0 209 201 0 224 201 0
|
1
TestLevel.tmx.2
Normal file
1
TestLevel.tmx.2
Normal file
@ -0,0 +1 @@
|
|||||||
|
97 384 0 97 400 0 97 416 0 97 432 0 97 448 0 102 464 0 112 473 0 115 480 0 115 496 0 115 512 0 111 526 0 110 528 0 95 543 0 95 544 0 89 560 0 90 576 0 96 587 0 101 592 0 109 608 0 109 624 0 109 640 0 109 656 0 109 672 0 109 688 0 109 691 1 112 701 0 114 704 0 128 718 0 130 720 0 144 733 0 146 736 0 160 750 0 163 752 0 176 754 0 192 753 0 194 751 0 208 738 0 211 735 0 224 723 0 227 719 0 240 704 0 240 703 0 243 687 0 243 671 0 243 655 0 243 639 0 243 623 0 243 607 0 243 591 0 243 575 0 243 559 0 243 543 0 243 527 0 243 511 0 247 495 0 256 484 0 261 479 0 272 468 0 277 463 0 288 454 0 304 451 0 308 448 1 309 447 0 312 431 0 303 421 0 298 415 0 287 405 0 283 400 1 282 399 0 271 388 0 265 383 0 255 372 0 250 367 0 239 356 0 233 351 0 223 340 0 218 335 0 207 328 0 190 327 0 174 327 0 159 327 0 144 319 0 143 318 0 128 303 0 127 302 0 112 287 0 111 287 0 95 281 0 79 281 0 63 281 0 47 278 0 40 271 0 31 261 0 29 255 0 28 239 0 28 223 0 28 206 0 32 198 0 37 191 0 48 182 0 64 177 0 80 178 0 96 188 0 99 192 0 112 200 0 128 201 0 144 201 0 161 201 0 176 201 0 192 201 0 209 201 0 224 201 0
|
@ -42,6 +42,7 @@ All rights reserved.
|
|||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include "AnimationState.h"
|
#include "AnimationState.h"
|
||||||
#include "FloatingText.h"
|
#include "FloatingText.h"
|
||||||
|
#include "HamsterAI.h"
|
||||||
|
|
||||||
std::vector<Hamster>Hamster::HAMSTER_LIST;
|
std::vector<Hamster>Hamster::HAMSTER_LIST;
|
||||||
const uint8_t Hamster::MAX_HAMSTER_COUNT{100U};
|
const uint8_t Hamster::MAX_HAMSTER_COUNT{100U};
|
||||||
@ -71,14 +72,6 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
|
|||||||
if(h.IsPlayerControlled){
|
if(h.IsPlayerControlled){
|
||||||
h.HandlePlayerControls();
|
h.HandlePlayerControls();
|
||||||
}else{
|
}else{
|
||||||
if(!h.hamsterJet.has_value()){
|
|
||||||
h.ObtainPowerup(Powerup::JET);
|
|
||||||
Powerup tempJetPowerup{{},Powerup::JET};
|
|
||||||
tempJetPowerup.OnPowerupObtain(h);
|
|
||||||
h.SetState(FLYING);
|
|
||||||
h.lastSafeLocation.reset();
|
|
||||||
h.hamsterJet.emplace(h);
|
|
||||||
}
|
|
||||||
//TODO: NPC controls.
|
//TODO: NPC controls.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,7 +205,8 @@ void Hamster::LoadHamsters(const vf2d startingLoc){
|
|||||||
if(NPC_HAMSTER_COUNT+1>MAX_HAMSTER_COUNT)throw std::runtime_error{std::format("WARNING! Max hamster count is too high! Please expand the MAX_HAMSTER_COUNT if you want more hamsters. Requested {} hamsters.",MAX_HAMSTER_COUNT)};
|
if(NPC_HAMSTER_COUNT+1>MAX_HAMSTER_COUNT)throw std::runtime_error{std::format("WARNING! Max hamster count is too high! Please expand the MAX_HAMSTER_COUNT if you want more hamsters. Requested {} hamsters.",MAX_HAMSTER_COUNT)};
|
||||||
playerHamster=&HAMSTER_LIST.emplace_back(startingLoc,PLAYER_HAMSTER_IMAGE,PLAYER_CONTROLLED);
|
playerHamster=&HAMSTER_LIST.emplace_back(startingLoc,PLAYER_HAMSTER_IMAGE,PLAYER_CONTROLLED);
|
||||||
for(int i:std::ranges::iota_view(0U,NPC_HAMSTER_COUNT)){
|
for(int i:std::ranges::iota_view(0U,NPC_HAMSTER_COUNT)){
|
||||||
HAMSTER_LIST.emplace_back(startingLoc,NPC_HAMSTER_IMAGES.at(util::random()%NPC_HAMSTER_IMAGES.size()),NPC);
|
Hamster&npcHamster{HAMSTER_LIST.emplace_back(startingLoc,NPC_HAMSTER_IMAGES.at(util::random()%NPC_HAMSTER_IMAGES.size()),NPC)};
|
||||||
|
npcHamster.ai.LoadAI(HamsterGame::Game().GetCurrentMapName(),HamsterAI::AIType(util::random()%int(HamsterAI::AIType::END)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +329,7 @@ void Hamster::HandlePlayerControls(){
|
|||||||
if(lastTappedSpace<=0.6f&&HasPowerup(Powerup::JET)){
|
if(lastTappedSpace<=0.6f&&HasPowerup(Powerup::JET)){
|
||||||
SetState(FLYING);
|
SetState(FLYING);
|
||||||
lastSafeLocation.reset();
|
lastSafeLocation.reset();
|
||||||
|
if(IsPlayerControlled)HamsterAI::OnJetLaunch(this->pos);
|
||||||
hamsterJet.emplace(*this);
|
hamsterJet.emplace(*this);
|
||||||
}
|
}
|
||||||
lastTappedSpace=0.f;
|
lastTappedSpace=0.f;
|
||||||
@ -399,6 +394,7 @@ void Hamster::HandleCollision(){
|
|||||||
(!HasPowerup(powerup.GetType())||HasPowerup(Powerup::JET)&&powerup.GetType()==Powerup::JET&&jetFuel!=1.f)
|
(!HasPowerup(powerup.GetType())||HasPowerup(Powerup::JET)&&powerup.GetType()==Powerup::JET&&jetFuel!=1.f)
|
||||||
&&geom2d::overlaps(geom2d::circle<float>(GetPos(),collisionRadius),geom2d::circle<float>(powerup.GetPos(),20.f))){
|
&&geom2d::overlaps(geom2d::circle<float>(GetPos(),collisionRadius),geom2d::circle<float>(powerup.GetPos(),20.f))){
|
||||||
ObtainPowerup(powerup.GetType());
|
ObtainPowerup(powerup.GetType());
|
||||||
|
if(IsPlayerControlled)HamsterAI::OnPowerupCollection(this->pos);
|
||||||
powerup.OnPowerupObtain(*this);
|
powerup.OnPowerupObtain(*this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,6 +402,7 @@ void Hamster::HandleCollision(){
|
|||||||
if(z<=0.1f&&geom2d::overlaps(geom2d::rect<float>(checkpoint.GetPos()-vf2d{62,60},{122.f,113.f}),geom2d::circle<float>(GetPos(),collisionRadius))&&!checkpointsCollected.count(checkpoint.GetPos())){
|
if(z<=0.1f&&geom2d::overlaps(geom2d::rect<float>(checkpoint.GetPos()-vf2d{62,60},{122.f,113.f}),geom2d::circle<float>(GetPos(),collisionRadius))&&!checkpointsCollected.count(checkpoint.GetPos())){
|
||||||
checkpointsCollected.insert(checkpoint.GetPos());
|
checkpointsCollected.insert(checkpoint.GetPos());
|
||||||
FloatingText::CreateFloatingText(pos,std::format("{} / {}",checkpointsCollected.size(),Checkpoint::GetCheckpoints().size()),{WHITE,GREEN},{1.5f,2.f});
|
FloatingText::CreateFloatingText(pos,std::format("{} / {}",checkpointsCollected.size(),Checkpoint::GetCheckpoints().size()),{WHITE,GREEN},{1.5f,2.f});
|
||||||
|
if(IsPlayerControlled)HamsterAI::OnCheckpointCollected(this->pos);
|
||||||
checkpoint.OnCheckpointCollect();
|
checkpoint.OnCheckpointCollect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,6 +413,7 @@ void Hamster::HandleCollision(){
|
|||||||
burrowTimer=1.f;
|
burrowTimer=1.f;
|
||||||
enteredTunnel=id;
|
enteredTunnel=id;
|
||||||
burrowImgShrinkTimer=0.5f;
|
burrowImgShrinkTimer=0.5f;
|
||||||
|
if(IsPlayerControlled)HamsterAI::OnTunnelEnter(this->pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -539,12 +537,20 @@ const float&Hamster::GetZ()const{
|
|||||||
|
|
||||||
void Hamster::SetPos(const vf2d pos){
|
void Hamster::SetPos(const vf2d pos){
|
||||||
bool movedY{false};
|
bool movedY{false};
|
||||||
|
bool movedX{false};
|
||||||
if(state==FLYING&&HamsterGame::Game().IsInBounds(vf2d{this->pos.x,pos.y})||!HamsterGame::Game().IsTerrainSolid(vf2d{this->pos.x,pos.y})){
|
if(state==FLYING&&HamsterGame::Game().IsInBounds(vf2d{this->pos.x,pos.y})||!HamsterGame::Game().IsTerrainSolid(vf2d{this->pos.x,pos.y})){
|
||||||
this->pos=vf2d{this->pos.x,pos.y};
|
this->pos=vf2d{this->pos.x,pos.y};
|
||||||
movedY=true;
|
movedY=true;
|
||||||
}
|
}
|
||||||
if(state==FLYING&&HamsterGame::Game().IsInBounds(vf2d{pos.x,this->pos.y})||!HamsterGame::Game().IsTerrainSolid(vf2d{pos.x,this->pos.y}))this->pos=vf2d{pos.x,this->pos.y};
|
if(state==FLYING&&HamsterGame::Game().IsInBounds(vf2d{pos.x,this->pos.y})||!HamsterGame::Game().IsTerrainSolid(vf2d{pos.x,this->pos.y})){
|
||||||
if (!movedY&&(state==FLYING&&HamsterGame::Game().IsInBounds(vf2d{this->pos.x,pos.y})||!HamsterGame::Game().IsTerrainSolid(vf2d{this->pos.x,pos.y})))this->pos=vf2d{this->pos.x,pos.y};
|
this->pos=vf2d{pos.x,this->pos.y};
|
||||||
|
movedX=true;
|
||||||
|
}
|
||||||
|
if (!movedY&&(state==FLYING&&HamsterGame::Game().IsInBounds(vf2d{this->pos.x,pos.y})||!HamsterGame::Game().IsTerrainSolid(vf2d{this->pos.x,pos.y}))){
|
||||||
|
this->pos=vf2d{this->pos.x,pos.y};
|
||||||
|
movedY=true;
|
||||||
|
}
|
||||||
|
if(IsPlayerControlled&&(movedX||movedY))HamsterAI::OnMove(this->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hamster::SetZ(const float z){
|
void Hamster::SetZ(const float z){
|
||||||
|
@ -45,6 +45,7 @@ All rights reserved.
|
|||||||
#include "HamsterJet.h"
|
#include "HamsterJet.h"
|
||||||
#include "HamsterGame.h"
|
#include "HamsterGame.h"
|
||||||
#include "Checkpoint.h"
|
#include "Checkpoint.h"
|
||||||
|
#include "HamsterAI.h"
|
||||||
|
|
||||||
using Timer=float;
|
using Timer=float;
|
||||||
|
|
||||||
@ -120,6 +121,7 @@ class Hamster{
|
|||||||
float burrowTimer{};
|
float burrowTimer{};
|
||||||
float burrowImgShrinkTimer{};
|
float burrowImgShrinkTimer{};
|
||||||
uint16_t enteredTunnel{};
|
uint16_t enteredTunnel{};
|
||||||
|
HamsterAI ai;
|
||||||
public:
|
public:
|
||||||
Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled=NPC);
|
Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled=NPC);
|
||||||
static const Hamster&GetPlayer();
|
static const Hamster&GetPlayer();
|
||||||
|
133
src/HamsterAI.cpp
Normal file
133
src/HamsterAI.cpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
#pragma region License
|
||||||
|
/*
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
Portions of this software are copyright © 2024 The FreeType
|
||||||
|
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma endregion
|
||||||
|
#include "HamsterAI.h"
|
||||||
|
#include "HamsterGame.h"
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
bool HamsterAI::recordingMode{false};
|
||||||
|
std::optional<vi2d>HamsterAI::lastTileWalkedOn;
|
||||||
|
std::vector<HamsterAI::Action>HamsterAI::recordedActions;
|
||||||
|
|
||||||
|
void HamsterAI::Update(const float fElapsedTime){
|
||||||
|
if(HamsterGame::Game().GetKey(HOME).bPressed){
|
||||||
|
if(!recordingMode){
|
||||||
|
recordingMode=true;
|
||||||
|
recordedActions.clear();
|
||||||
|
}else{
|
||||||
|
HamsterGame::Game().TextEntryEnable(true,"0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HamsterAI::DrawOverlay(){
|
||||||
|
if(recordingMode){
|
||||||
|
if(HamsterGame::Game().IsTextEntryEnabled()){
|
||||||
|
std::string displayStr{std::format("{}\n{}","0=SMART 1=NORMAL 2=DUMB",HamsterGame::Game().TextEntryGetString())};
|
||||||
|
for(int y:std::ranges::iota_view(-1,2)){
|
||||||
|
for(int x:std::ranges::iota_view(-1,2)){
|
||||||
|
HamsterGame::Game().DrawStringDecal({2.f+x,2.f+y},displayStr,BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HamsterGame::Game().DrawStringDecal({2.f,2.f},displayStr,YELLOW);
|
||||||
|
}else if(fmod(HamsterGame::Game().GetRuntime(),1.f)<0.5f){
|
||||||
|
for(int y:std::ranges::iota_view(-1,2)){
|
||||||
|
for(int x:std::ranges::iota_view(-1,2)){
|
||||||
|
HamsterGame::Game().DrawStringDecal({2.f+x,2.f+y},"RECORDING",BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HamsterGame::Game().DrawStringDecal({2.f,2.f},"RECORDING",RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void HamsterAI::OnTextEntryComplete(const std::string&enteredText){
|
||||||
|
if(recordingMode){
|
||||||
|
std::ofstream file{std::format("{}.{}",HamsterGame::Game().GetCurrentMapName(),stoi(enteredText))};
|
||||||
|
for(const Action&action:recordedActions){
|
||||||
|
file<<action.pos.x<<' '<<action.pos.y<<' '<<int(action.type)<<' ';
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
recordedActions.clear();
|
||||||
|
recordingMode=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const HamsterAI::ActionOptRef HamsterAI::GetCurrentAction(){
|
||||||
|
if(actionInd<actionsToPerform.size())return ActionOptRef{actionsToPerform.at(actionInd)};
|
||||||
|
|
||||||
|
}
|
||||||
|
const HamsterAI::ActionOptRef HamsterAI::AdvanceToNextAction(){
|
||||||
|
actionInd++;
|
||||||
|
return GetCurrentAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HamsterAI::OnMove(const vi2d pos){
|
||||||
|
const vi2d tilePos{vi2d{pos/16}*16};
|
||||||
|
if(!lastTileWalkedOn.has_value()){
|
||||||
|
recordedActions.emplace_back(pos,Action::MOVE);
|
||||||
|
}else if(lastTileWalkedOn.value()!=tilePos){
|
||||||
|
recordedActions.emplace_back(pos,Action::MOVE);
|
||||||
|
}
|
||||||
|
lastTileWalkedOn=tilePos;
|
||||||
|
}
|
||||||
|
void HamsterAI::OnPowerupCollection(const vi2d pos){
|
||||||
|
recordedActions.emplace_back(pos,Action::COLLECT_POWERUP);
|
||||||
|
}
|
||||||
|
void HamsterAI::OnJetLaunch(const vi2d pos){
|
||||||
|
recordedActions.emplace_back(pos,Action::LAUNCH_JET);
|
||||||
|
}
|
||||||
|
void HamsterAI::OnTunnelEnter(const vi2d pos){
|
||||||
|
recordedActions.emplace_back(pos,Action::ENTER_TUNNEL);
|
||||||
|
}
|
||||||
|
void HamsterAI::OnCheckpointCollected(const vi2d pos){
|
||||||
|
recordedActions.emplace_back(pos,Action::CHECKPOINT_COLLECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HamsterAI::LoadAI(const std::string&mapName,AIType type){
|
||||||
|
std::ifstream file{std::format("{}.{}",HamsterGame::Game().GetCurrentMapName(),int(type))};
|
||||||
|
actionsToPerform.clear();
|
||||||
|
while(file.good()){
|
||||||
|
Action newAction;
|
||||||
|
file>>newAction.pos.x;
|
||||||
|
file>>newAction.pos.y;
|
||||||
|
int typeNum;
|
||||||
|
file>>typeNum;
|
||||||
|
newAction.type=HamsterAI::Action::ActionType(typeNum);
|
||||||
|
actionsToPerform.emplace_back(newAction);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
83
src/HamsterAI.h
Normal file
83
src/HamsterAI.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma region License
|
||||||
|
/*
|
||||||
|
License (OLC-3)
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions or derivations of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions or derivative works in binary form must reproduce the above
|
||||||
|
copyright notice. This list of conditions and the following disclaimer must be
|
||||||
|
reproduced in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||||
|
be used to endorse or promote products derived from this software without specific
|
||||||
|
prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
|
||||||
|
Portions of this software are copyright © 2024 The FreeType
|
||||||
|
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||||
|
All rights reserved.
|
||||||
|
*/
|
||||||
|
#pragma endregion
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include "olcUTIL_Geometry2D.h"
|
||||||
|
|
||||||
|
class HamsterAI{
|
||||||
|
public:
|
||||||
|
class Action{
|
||||||
|
public:
|
||||||
|
enum ActionType{
|
||||||
|
MOVE,
|
||||||
|
COLLECT_POWERUP,
|
||||||
|
LAUNCH_JET,
|
||||||
|
ENTER_TUNNEL,
|
||||||
|
CHECKPOINT_COLLECTED,
|
||||||
|
};
|
||||||
|
vi2d pos;
|
||||||
|
ActionType type;
|
||||||
|
};
|
||||||
|
enum AIType{
|
||||||
|
SMART,
|
||||||
|
NORMAL,
|
||||||
|
DUMB,
|
||||||
|
END, //NOTE: Not at AI type, just used for iteration detection.
|
||||||
|
};
|
||||||
|
using ActionOptRef=std::optional<std::reference_wrapper<HamsterAI::Action>>;
|
||||||
|
const ActionOptRef GetCurrentAction();
|
||||||
|
const ActionOptRef AdvanceToNextAction();
|
||||||
|
void LoadAI(const std::string&mapName,AIType type);
|
||||||
|
|
||||||
|
static void OnMove(const vi2d pos);
|
||||||
|
static void OnPowerupCollection(const vi2d pos);
|
||||||
|
static void OnJetLaunch(const vi2d pos);
|
||||||
|
static void OnTunnelEnter(const vi2d pos);
|
||||||
|
static void OnCheckpointCollected(const vi2d pos);
|
||||||
|
|
||||||
|
static void OnTextEntryComplete(const std::string&enteredText);
|
||||||
|
|
||||||
|
static void Update(const float fElapsedTime);
|
||||||
|
static void DrawOverlay();
|
||||||
|
private:
|
||||||
|
static bool recordingMode;
|
||||||
|
static std::vector<Action>recordedActions;
|
||||||
|
std::vector<Action>actionsToPerform;
|
||||||
|
size_t actionInd{};
|
||||||
|
static std::optional<vi2d>lastTileWalkedOn; //In World Coords
|
||||||
|
};
|
@ -5,6 +5,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "Checkpoint.h"
|
#include "Checkpoint.h"
|
||||||
#include "FloatingText.h"
|
#include "FloatingText.h"
|
||||||
|
#include "HamsterAI.h"
|
||||||
|
|
||||||
geom2d::rect<float>HamsterGame::SCREEN_FRAME{{96,0},{320,288}};
|
geom2d::rect<float>HamsterGame::SCREEN_FRAME{{96,0},{320,288}};
|
||||||
std::unordered_map<std::string,Animate2D::Animation<AnimationState::AnimationState>>HamsterGame::ANIMATIONS;
|
std::unordered_map<std::string,Animate2D::Animation<AnimationState::AnimationState>>HamsterGame::ANIMATIONS;
|
||||||
@ -120,6 +121,7 @@ void HamsterGame::LoadLevel(const std::string&mapName){
|
|||||||
const vf2d levelSpawnLoc{50,50}; //TEMPORARY
|
const vf2d levelSpawnLoc{50,50}; //TEMPORARY
|
||||||
|
|
||||||
currentMap=TMXParser{ASSETS_DIR+mapName};
|
currentMap=TMXParser{ASSETS_DIR+mapName};
|
||||||
|
currentMapName=mapName;
|
||||||
cloudSpd.x=util::random_range(-12.f,12.f);
|
cloudSpd.x=util::random_range(-12.f,12.f);
|
||||||
cloudSpd.y=util::random_range(-0.3f,0.3f);
|
cloudSpd.y=util::random_range(-0.3f,0.3f);
|
||||||
cloudOffset.x=util::random();
|
cloudOffset.x=util::random();
|
||||||
@ -181,6 +183,7 @@ void HamsterGame::UpdateGame(const float fElapsedTime){
|
|||||||
camera.SetLazyFollowRate(4.f*Hamster::GetPlayer().GetMaxSpeed()/128.f);
|
camera.SetLazyFollowRate(4.f*Hamster::GetPlayer().GetMaxSpeed()/128.f);
|
||||||
tv.SetWorldOffset(tv.ScaleToWorld(-SCREEN_FRAME.pos)+camera.GetViewPosition());
|
tv.SetWorldOffset(tv.ScaleToWorld(-SCREEN_FRAME.pos)+camera.GetViewPosition());
|
||||||
Hamster::UpdateHamsters(fElapsedTime);
|
Hamster::UpdateHamsters(fElapsedTime);
|
||||||
|
HamsterAI::Update(fElapsedTime);
|
||||||
Powerup::UpdatePowerups(fElapsedTime);
|
Powerup::UpdatePowerups(fElapsedTime);
|
||||||
Checkpoint::UpdateCheckpoints(fElapsedTime);
|
Checkpoint::UpdateCheckpoints(fElapsedTime);
|
||||||
FloatingText::UpdateFloatingText(fElapsedTime);
|
FloatingText::UpdateFloatingText(fElapsedTime);
|
||||||
@ -209,6 +212,7 @@ void HamsterGame::DrawGame(){
|
|||||||
FloatingText::DrawFloatingText(tv);
|
FloatingText::DrawFloatingText(tv);
|
||||||
border.Draw();
|
border.Draw();
|
||||||
Hamster::DrawOverlay();
|
Hamster::DrawOverlay();
|
||||||
|
HamsterAI::DrawOverlay();
|
||||||
#pragma region Powerup Display
|
#pragma region Powerup Display
|
||||||
for(int y:std::ranges::iota_view(0,4)){
|
for(int y:std::ranges::iota_view(0,4)){
|
||||||
for(int x:std::ranges::iota_view(0,2)){
|
for(int x:std::ranges::iota_view(0,2)){
|
||||||
@ -528,6 +532,14 @@ const Terrain::Direction&HamsterGame::GetTileFacingDirection(const vf2d worldPos
|
|||||||
return tileFacingDir;
|
return tileFacingDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string&HamsterGame::GetCurrentMapName()const{
|
||||||
|
return currentMapName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HamsterGame::OnTextEntryComplete(const std::string& sText){
|
||||||
|
HamsterAI::OnTextEntryComplete(sText);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
HamsterGame game("Project Hamster");
|
HamsterGame game("Project Hamster");
|
||||||
|
@ -81,6 +81,8 @@ public:
|
|||||||
const float GetCameraZ()const;
|
const float GetCameraZ()const;
|
||||||
const std::unordered_map<TunnelId,Tunnel>&GetTunnels()const;
|
const std::unordered_map<TunnelId,Tunnel>&GetTunnels()const;
|
||||||
const Terrain::Direction&GetTileFacingDirection(const vf2d worldPos)const;
|
const Terrain::Direction&GetTileFacingDirection(const vf2d worldPos)const;
|
||||||
|
const std::string&GetCurrentMapName()const;
|
||||||
|
virtual void OnTextEntryComplete(const std::string& sText)override;
|
||||||
private:
|
private:
|
||||||
void UpdateGame(const float fElapsedTime);
|
void UpdateGame(const float fElapsedTime);
|
||||||
void DrawGame();
|
void DrawGame();
|
||||||
@ -114,4 +116,5 @@ private:
|
|||||||
void DrawRadar();
|
void DrawRadar();
|
||||||
float radarScale{48.f};
|
float radarScale{48.f};
|
||||||
std::vector<Renderable>waterTiles;
|
std::vector<Renderable>waterTiles;
|
||||||
|
std::string currentMapName;
|
||||||
};
|
};
|
@ -79,6 +79,15 @@ AI will move towards those nodes as best they can. If they get stuck for some am
|
|||||||
Record each collection of a powerup/launch moment as these are important nodes for AI to be on. (Maybe "Cheat" the AI a little if thier stuck node counte i really high by teleporting them when they are off-screen)
|
Record each collection of a powerup/launch moment as these are important nodes for AI to be on. (Maybe "Cheat" the AI a little if thier stuck node counte i really high by teleporting them when they are off-screen)
|
||||||
|
|
||||||
|
|
||||||
|
Important Events:
|
||||||
|
|
||||||
|
Powerup Collection
|
||||||
|
Jet Launch
|
||||||
|
Tunnel Enter
|
||||||
|
New Tile Traversal
|
||||||
|
|
||||||
|
Be careful about changing maps as AI must then be re-recorded!!!
|
||||||
|
|
||||||
|
|
||||||
LORE
|
LORE
|
||||||
===================
|
===================
|
||||||
|
Loading…
x
Reference in New Issue
Block a user