From 115c33526d25a0773419156d57e274b44494e2f2 Mon Sep 17 00:00:00 2001 From: Rtch90 Date: Sat, 14 Apr 2018 16:51:33 +0100 Subject: [PATCH] [Add] Start of ship ai. --- src/Makefile.am | 4 +-- src/ai_ship.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++ src/ai_ship.h | 32 ++++++++++++++++++++ src/body.cpp | 4 +++ src/main.cpp | 12 +++++--- src/object.h | 2 +- src/serializer.h | 1 + src/ship.cpp | 22 ++++++++++++++ src/ship.h | 1 + src/ship_type.cpp | 4 +-- 10 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 src/ai_ship.cpp create mode 100644 src/ai_ship.h diff --git a/src/Makefile.am b/src/Makefile.am index bb1f974..66e5d4a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h planet.h player.h dynamic_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \ system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h model_body.h gui_iselectable.h \ ship_type.h object.h info_view.h model_coll_mesh_data.h object_viewer_view.h fixed.h custom_starsystems.h gameconsts.h \ - aabb.h serializer.h sfx.h + aabb.h serializer.h sfx.h ai_ship.h libgui_a_SOURCES = gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cpp gui_label.cpp gui_toggle_button.cpp gui_radio_button.cpp \ gui_radio_group.cpp gui_image_button.cpp gui_image.cpp gui_image_radio_button.cpp gui_multi_state_image_button.cpp gui_widget.cpp \ @@ -20,7 +20,7 @@ Lephisto3D_SOURCES = main.cpp glfreetype.cpp body.cpp space.cpp ship.cpp player. star.cpp frame.cpp ship_cpanel.cpp sector_view.cpp mtrand.cpp world_view.cpp system_view.cpp \ star_system.cpp sector.cpp system_info_view.cpp generic_system_view.cpp date.cpp space_station.cpp \ space_station_view.cpp model_body.cpp ship_type.cpp info_view.cpp model_coll_mesh_data.cpp \ - object_viewer_view.cpp custom_starsystems.cpp serializer.cpp sfx.cpp + object_viewer_view.cpp custom_starsystems.cpp serializer.cpp sfx.cpp ai_ship.cpp Lephisto3D_LDADD = sbre/libsbre.a collider/libcollider.a libgui.a ModelViewer_SOURCES = sbre_viewer.cpp glfreetype.cpp diff --git a/src/ai_ship.cpp b/src/ai_ship.cpp new file mode 100644 index 0000000..eb149ca --- /dev/null +++ b/src/ai_ship.cpp @@ -0,0 +1,77 @@ +#include "libs.h" +#include "ai_ship.h" +#include "serializer.h" +#include "l3d.h" + +bool AIShip::DoKill(const Ship* enemy) { + /* Need to deal with frames, large distances, and success! */ + if(GetFrame() == enemy->GetFrame()) { + vector3d dir = vector3d::Normalize(enemy->GetPosition() - GetPosition()); + AIFaceDirection(dir); + } + return false; +} + +void AIShip::TimeStepUpdate(const float timeStep) { + bool done = false; + + if(m_todo.size() != 0) { + Instruction& inst = m_todo.front(); + switch(inst.cmd) { + case DO_KILL: + done = DoKill(static_cast(inst.arg)); + break; + case DO_NOTHING: done = true; break; + } + } + if(done) { + printf("AI '%s' successfully executed %d:'%s'\n", GetLabel().c_str(), m_todo.front().cmd, + static_cast(m_todo.front().arg)->GetLabel().c_str()); + m_todo.pop_front(); + } + + Ship::TimeStepUpdate(timeStep); +} + +void AIShip::Save(void) { + using namespace Serializer::Write; + Ship::Save(); + wr_int(m_todo.size()); + for(std::list::iterator i = m_todo.begin(); i != m_todo.end(); ++i) { + wr_int((int)(*i).cmd); + switch((*i).cmd) { + case DO_KILL: + wr_int(Serializer::LookupBody(static_cast((*i).arg))); + case DO_NOTHING: wr_int(0); break; + } + } +} + +void AIShip::Load(void) { + using namespace Serializer::Read; + Ship::Load(); + int num = rd_int(); + while(num-- > 0) { + Command c= (Command)rd_int(); + void* arg = (void*)rd_int(); + printf("COMMAND %d:%p\n", c, arg); + m_todo.push_back(Instruction(c, arg)); + } +} + +void AIShip::PostLoadFixup(void) { + Ship::PostLoadFixup(); + for(std::list::iterator i = m_todo.begin(); i != m_todo.end(); ++i) { + switch((*i).cmd) { + case DO_KILL: + (*i).arg = Serializer::LookupBody((size_t)(*i).arg); + break; + case DO_NOTHING: break; + } + } +} + +void AIShip::Instruct(enum Command cmd, void* arg) { + m_todo.push_back(Instruction(cmd, arg)); +} + diff --git a/src/ai_ship.h b/src/ai_ship.h new file mode 100644 index 0000000..6b08328 --- /dev/null +++ b/src/ai_ship.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include "ship.h" +#include "ship_type.h" + +class AIShip: public Ship { +public: + OBJDEF(AIShip, Ship, AISHIP); + AIShip(ShipType::Type shipType): Ship(shipType) { } + AIShip(void): Ship() { } + void TimeStepUpdate(const float timeStep); + + enum Command { DO_NOTHING, DO_KILL }; + void Instruct(enum Command, void* arg); + void ClearInstructions(void) { m_todo.clear(); } + virtual void PostLoadFixup(void); + +protected: + virtual void Save(void); + virtual void Load(void); +private: + bool DoKill(const Ship*); + class Instruction { + public: + Command cmd; + void* arg; + Instruction(Command c, void* a): cmd(c), arg(a) { } + }; + + std::list m_todo; +}; + diff --git a/src/body.cpp b/src/body.cpp index 3db9ced..6714b1d 100644 --- a/src/body.cpp +++ b/src/body.cpp @@ -6,6 +6,7 @@ #include "planet.h" #include "space_station.h" #include "ship.h" +#include "ai_ship.h" #include "player.h" #include "sfx.h" @@ -48,6 +49,7 @@ void Body::Serialize(void) { case Object::PLANET: case Object::SPACESTATION: case Object::SHIP: + case Object::AISHIP: case Object::PLAYER: case Object::SFX: Save(); @@ -74,6 +76,8 @@ Body* Body::Unserialize(void) { b = new SpaceStation(); break; case Object::SHIP: b = new Ship(); break; + case Object::AISHIP: + b = new AIShip(); break; case Object::PLAYER: b = new Player(); break; case Object::SFX: diff --git a/src/main.cpp b/src/main.cpp index 7938e9a..5bf4786 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,7 @@ #include "space_station_view.h" #include "info_view.h" #include "serializer.h" +#include "ai_ship.h" float L3D::timeAccel = 1.0f; int L3D::scrWidth; @@ -201,11 +202,12 @@ void L3D::HandleEvents(void) { station->SetPosition(L3D::player->GetPosition()+5000.0*dir); Space::AddBody(station); } else { - Ship* body = new Ship(ShipType::LADYBIRD); - body->SetLabel("A Friend"); - body->SetFrame(L3D::player->GetFrame()); - body->SetPosition(L3D::player->GetPosition()+1000.0*dir); - Space::AddBody(body); + AIShip* ship = new AIShip(ShipType::LADYBIRD); + ship->Instruct(AIShip::DO_KILL, L3D::player); + ship->SetLabel("A friend?"); + ship->SetFrame(L3D::player->GetFrame()); + ship->SetPosition(L3D::player->GetPosition()+100.0*dir); + Space::AddBody(ship); } } #endif diff --git a/src/object.h b/src/object.h index 53cb1ce..ca3fc48 100644 --- a/src/object.h +++ b/src/object.h @@ -2,7 +2,7 @@ class Object { public: - enum Type { OBJECT, BODY, MODELBODY, DYNAMICBODY, SHIP, PLAYER, SPACESTATION, PLANET, STAR, SFX }; + enum Type { OBJECT, BODY, MODELBODY, DYNAMICBODY, SHIP, PLAYER, SPACESTATION, PLANET, STAR, SFX, AISHIP }; virtual Type GetType(void) { return OBJECT; } virtual bool IsType(Type c) { return GetType() == c; } }; diff --git a/src/serializer.h b/src/serializer.h index 0caec26..c18205a 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -1,6 +1,7 @@ #pragma once #include #include "libs.h" +#include "star_system.h" #define SAVEFILE_VERSION 1 diff --git a/src/ship.cpp b/src/ship.cpp index da2214e..6a0badd 100644 --- a/src/ship.cpp +++ b/src/ship.cpp @@ -397,6 +397,28 @@ void Ship::SetCombatTarget(Body* const target) { L3D::worldView->UpdateCommsOptions(); } +/* Orient so our -ve z axis == dir. ie.. So that direction points forwards. */ +void Ship::AIFaceDirection(const vector3d& dir) { + matrix4x4d rot; + GetRotMatrix(rot); + rot = rot.InverseOf(); + const vector3d zaxis = vector3d(-rot[2], -rot[6], -rot[10]); + vector3d rotaxis = vector3d::Cross(zaxis, dir); + const float dot = vector3d::Dot(dir, zaxis); + /* If facing > 90 degrees away then max turn rate.. */ + if(dot < 0) rotaxis.Normalize(); + rotaxis = rot*rotaxis; + ClearThrusterState(); + /* We still must apply rotation damping. */ + rotaxis -= CalcRotDamping(); + SetAngThrusterState(0, rotaxis.x); + SetAngThrusterState(1, rotaxis.y); + SetAngThrusterState(2, rotaxis.z); + if(dot > 0) SetThrusterState(ShipType::THRUSTER_REAR, 1.0); + if(dot > 0.95f) SetGunState(0,1); + else SetGunState(0,0); +} + bool Ship::IsFiringLasers(void) { for(int i = 0; i < ShipType::GUNMOUNT_MAX; i++) { if(m_gunState[i]) return true; diff --git a/src/ship.h b/src/ship.h index 39ed215..e4117f5 100644 --- a/src/ship.h +++ b/src/ship.h @@ -46,6 +46,7 @@ public: enum FlightState { FLYING, LANDED }; FlightState GetFlightState(void) const { return m_flightState; } float GetWheelState(void) const { return m_wheelState; } + void AIFaceDirection(const vector3d& dir); EquipSet m_equipment; diff --git a/src/ship_type.cpp b/src/ship_type.cpp index a757817..97d6afb 100644 --- a/src/ship_type.cpp +++ b/src/ship_type.cpp @@ -21,8 +21,8 @@ const ShipType ShipType::types[] = { * I should outsource name choosing, or this happens.. */ "Ladybird Starfighter", - 13, - { 1e7, -1e7, 1e6, -1e6, -1e6, 1e6 }, + 62, + { 1e8, -1e8, 1e8, -1e8, -1e8, 1e8 }, 1e7, { { vector3f(0, -0.5, 0), vector3f(0, 0, -1) },