10 enemies in demo
This commit is contained in:
@@ -9,38 +9,48 @@
|
||||
*/
|
||||
|
||||
#include "states/game/enemy/enemy.hpp"
|
||||
#include "loaders/3d/obj_loader/obj_loader.hpp"
|
||||
#include <file/file_utils.hpp>
|
||||
#include <functional>
|
||||
#include "debug/debug.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::Math;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
Enemy::Enemy(TextureRepository* repo) {
|
||||
ObjLoader loader;
|
||||
Enemy::Enemy(Engine* engine, const EnemyInfo& t_info) {
|
||||
info = t_info;
|
||||
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.animation.count = 6;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = 250.0F;
|
||||
mesh = new DynamicMesh(*info.motherMesh);
|
||||
|
||||
auto* data = loader.load(FileUtils::fromCwd("game/models/zombie/zombie.obj"),
|
||||
objOptions);
|
||||
data->normalsEnabled = false;
|
||||
mesh = new DynamicMesh(*data);
|
||||
auto* bodyMaterial = mesh->getMaterialByName("BodyMaterial");
|
||||
auto* clothMaterial = mesh->getMaterialByName("ClothMaterial");
|
||||
|
||||
delete data;
|
||||
TYRA_ASSERT(bodyMaterial != nullptr && clothMaterial != nullptr,
|
||||
"Body and cloth materials not found!");
|
||||
|
||||
mesh->playAnimation(0, mesh->frames.size() - 1);
|
||||
mesh->setAnimSpeed(0.1F);
|
||||
info.bodyTexture->addLink(bodyMaterial->id);
|
||||
info.clothTexture->addLink(clothMaterial->id);
|
||||
|
||||
repo->addByMesh(mesh, FileUtils::fromCwd("game/models/zombie/"), "png");
|
||||
float r = Math::randomf(64.0F, 128.0F);
|
||||
float g = Math::randomf(64.0F, 128.0F);
|
||||
float b = Math::randomf(64.0F, 128.0F);
|
||||
|
||||
bodyMaterial->ambient.set(r, g, b);
|
||||
clothMaterial->ambient.set(r, g, b);
|
||||
|
||||
walkSequence = {0, 1, 2};
|
||||
fightSequence = {3, 4, 5};
|
||||
|
||||
mesh->setPosition(info.spawnPoint);
|
||||
|
||||
mesh->animation.setSequence(walkSequence);
|
||||
mesh->animation.loop = true;
|
||||
mesh->animation.setCallback(
|
||||
std::bind(&Enemy::animationCallback, this, std::placeholders::_1));
|
||||
mesh->translation.translateY(-5.0F);
|
||||
|
||||
audio = &engine->audio;
|
||||
audio->adpcm.setVolume(50, info.adpcmChannel);
|
||||
|
||||
allocateOptions();
|
||||
|
||||
pair = new RendererDynamicPair{mesh, options};
|
||||
@@ -58,14 +68,10 @@ void Enemy::update(const Heightmap& heightmap, const Vec4& playerPosition) {
|
||||
auto diff = *enemyPosition - playerPosition;
|
||||
auto ang = Math::atan2(diff.x, diff.z);
|
||||
|
||||
if (diff.length() > 30.0F) {
|
||||
diff.normalize();
|
||||
const float speed = 1.5F;
|
||||
auto nextPos = *enemyPosition - diff * speed;
|
||||
nextPos.y = heightmap.getHeightOffset(nextPos) - 60.0F;
|
||||
|
||||
mesh->translation.identity();
|
||||
mesh->translation.translate(nextPos);
|
||||
if (diff.length() > 110.0F) {
|
||||
walk(heightmap, diff);
|
||||
} else {
|
||||
fight();
|
||||
}
|
||||
|
||||
const float naturalRotation = 3.1F;
|
||||
@@ -73,7 +79,43 @@ void Enemy::update(const Heightmap& heightmap, const Vec4& playerPosition) {
|
||||
ang += naturalRotation;
|
||||
mesh->rotation.rotateByAngle(ang, Vec4(0.0F, 1.0F, 0.0F, 0.0F));
|
||||
|
||||
mesh->animate();
|
||||
mesh->update();
|
||||
}
|
||||
|
||||
void Enemy::walk(const Heightmap& heightmap, const Vec4& positionDiff) {
|
||||
if (isFighting) {
|
||||
mesh->animation.setSequence(walkSequence);
|
||||
}
|
||||
|
||||
isFighting = false;
|
||||
isWalking = true;
|
||||
|
||||
auto* enemyPosition = mesh->getPosition();
|
||||
auto normalized = positionDiff;
|
||||
normalized.normalize();
|
||||
const float speed = 2.5F;
|
||||
auto nextPos = *enemyPosition - normalized * speed;
|
||||
nextPos.y = heightmap.getHeightOffset(nextPos) - 60.0F;
|
||||
|
||||
mesh->translation.identity();
|
||||
mesh->translation.translate(nextPos);
|
||||
}
|
||||
|
||||
void Enemy::fight() {
|
||||
if (isWalking) {
|
||||
mesh->animation.setSequence(fightSequence);
|
||||
}
|
||||
|
||||
isFighting = true;
|
||||
isWalking = false;
|
||||
}
|
||||
|
||||
void Enemy::animationCallback(const AnimationSequenceCallback& callback) {
|
||||
if (callback == AnimationSequenceCallback::AnimationSequenceCallback_Loop) {
|
||||
if (isFighting) {
|
||||
audio->adpcm.tryPlay(info.adpcmSample, info.adpcmChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Enemy::allocateOptions() { options = new DynPipOptions(); }
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
# _____ ____ ___
|
||||
# | \/ ____| |___|
|
||||
# | | | \ | |
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2022, tyra - https://github.com/h4570/tyra
|
||||
# Licensed under Apache License 2.0
|
||||
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
|
||||
*/
|
||||
|
||||
#include "states/game/enemy/enemy_manager.hpp"
|
||||
#include "loaders/3d/obj_loader/obj_loader.hpp"
|
||||
#include <file/file_utils.hpp>
|
||||
#include <functional>
|
||||
#include "debug/debug.hpp"
|
||||
|
||||
using Tyra::FileUtils;
|
||||
using Tyra::Math;
|
||||
using Tyra::ObjLoader;
|
||||
using Tyra::ObjLoaderOptions;
|
||||
|
||||
namespace Demo {
|
||||
|
||||
EnemyManager::EnemyManager(Engine* engine, const Heightmap& heightmap) {
|
||||
textureRepo = &engine->renderer.core.texture.repository;
|
||||
|
||||
ObjLoader loader;
|
||||
ObjLoaderOptions objOptions;
|
||||
objOptions.animation.count = 6;
|
||||
objOptions.flipUVs = true;
|
||||
objOptions.scale = 250.0F;
|
||||
|
||||
auto* data = loader.load(FileUtils::fromCwd("game/models/zombie/zombie.obj"),
|
||||
objOptions);
|
||||
data->normalsEnabled = false;
|
||||
motherMesh = new DynamicMesh(*data);
|
||||
|
||||
delete data;
|
||||
|
||||
bodyTexture = textureRepo->add(
|
||||
FileUtils::fromCwd("game/models/zombie/BodyMaterial.png"));
|
||||
|
||||
clothTexture = textureRepo->add(
|
||||
FileUtils::fromCwd("game/models/zombie/ClothMaterial.png"));
|
||||
|
||||
auto* sample = engine->audio.adpcm.load(
|
||||
FileUtils::fromCwd("game/models/zombie/punch.adpcm"));
|
||||
|
||||
const int enemyCount = 10;
|
||||
for (int i = 0; i < enemyCount; i++) {
|
||||
EnemyInfo info;
|
||||
info.adpcmChannel = 9 + i;
|
||||
info.adpcmSample = sample;
|
||||
info.motherMesh = motherMesh;
|
||||
info.clothTexture = clothTexture;
|
||||
info.bodyTexture = bodyTexture;
|
||||
info.spawnPoint =
|
||||
Vec4(Math::randomf(heightmap.leftUp.x, heightmap.rightDown.x), 0.0F,
|
||||
Math::randomf(heightmap.leftUp.z, heightmap.rightDown.z), 1.0F);
|
||||
enemies.push_back(new Enemy(engine, info));
|
||||
}
|
||||
}
|
||||
|
||||
EnemyManager::~EnemyManager() {
|
||||
for (auto* enemy : enemies) {
|
||||
delete enemy;
|
||||
}
|
||||
|
||||
delete motherMesh;
|
||||
|
||||
textureRepo->free(bodyTexture->id);
|
||||
textureRepo->free(clothTexture->id);
|
||||
}
|
||||
|
||||
std::vector<RendererDynamicPair*> EnemyManager::getPairs() const {
|
||||
std::vector<RendererDynamicPair*> result;
|
||||
|
||||
for (auto* enemy : enemies) {
|
||||
result.push_back(enemy->pair);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void EnemyManager::update(const Heightmap& heightmap,
|
||||
const Vec4& playerPosition) {
|
||||
for (auto* enemy : enemies) {
|
||||
enemy->update(heightmap, playerPosition);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Demo
|
||||
@@ -37,8 +37,8 @@ void GameState::onStart() {
|
||||
|
||||
auto* repository = &engine->renderer.core.texture.repository;
|
||||
player = new Player(engine);
|
||||
enemy = new Enemy(repository);
|
||||
terrain = new Terrain(repository);
|
||||
enemyManager = new EnemyManager(engine, terrain->heightmap);
|
||||
skybox = new Skybox(repository);
|
||||
dbgObj = new DebugObject(repository);
|
||||
|
||||
@@ -49,7 +49,7 @@ GlobalStateType GameState::onFinish() {
|
||||
if (!initialized) return STATE_EXIT;
|
||||
|
||||
delete player;
|
||||
delete enemy;
|
||||
delete enemyManager;
|
||||
delete terrain;
|
||||
delete skybox;
|
||||
delete dbgObj;
|
||||
@@ -59,7 +59,7 @@ GlobalStateType GameState::onFinish() {
|
||||
}
|
||||
|
||||
void GameState::update() {
|
||||
if (fpsChecker++ > 100) {
|
||||
if (fpsChecker++ > 50) {
|
||||
TYRA_LOG("FPS: ", engine->info.getFps());
|
||||
fpsChecker = 0;
|
||||
}
|
||||
@@ -71,13 +71,13 @@ void GameState::update() {
|
||||
dbgObj->setPosition(*cameraInfo.looksAt);
|
||||
|
||||
player->update(terrain->heightmap);
|
||||
enemy->update(terrain->heightmap, player->getPosition());
|
||||
enemyManager->update(terrain->heightmap, player->getPosition());
|
||||
|
||||
renderer.clear();
|
||||
{
|
||||
renderer.add(skybox->pair);
|
||||
renderer.add(player->pair);
|
||||
renderer.add(enemy->pair);
|
||||
renderer.add(enemyManager->getPairs());
|
||||
renderer.add(terrain->pair);
|
||||
renderer.add(dbgObj->pair);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ Player::Player(Engine* engine)
|
||||
pad = &engine->pad;
|
||||
position = Vec4(3.0F, 50.0F, 0.0F);
|
||||
camera.lookAt = Vec4(0.0F, 0.0F, -30.0F);
|
||||
speed = 3.5F;
|
||||
speed = 5.0F;
|
||||
}
|
||||
|
||||
Player::~Player() { delete pair; }
|
||||
|
||||
@@ -115,59 +115,6 @@ void Weapon::update() {
|
||||
}
|
||||
}
|
||||
|
||||
// float tX = 0.0F;
|
||||
// float tY = -3.0F;
|
||||
// float tZ = -10.0F;
|
||||
|
||||
// float rY = 0.1F;
|
||||
// float rZ = -4.3F;
|
||||
|
||||
// void Weapon::debugPosition(Pad* pad) {
|
||||
// const auto& leftJoy = pad->getLeftJoyPad();
|
||||
// const auto& rightJoy = pad->getRightJoyPad();
|
||||
// const float offset = 0.05F;
|
||||
|
||||
// if (leftJoy.v <= 100) {
|
||||
// rY -= offset;
|
||||
// } else if (leftJoy.v >= 200) {
|
||||
// rY += offset;
|
||||
// }
|
||||
// if (leftJoy.h <= 100) {
|
||||
// rZ -= offset;
|
||||
// } else if (leftJoy.h >= 200) {
|
||||
// rZ += offset;
|
||||
// }
|
||||
|
||||
// if (rightJoy.h <= 100) {
|
||||
// tY -= offset;
|
||||
// } else if (rightJoy.h >= 200) {
|
||||
// tY += offset;
|
||||
// }
|
||||
|
||||
// if (rightJoy.v <= 100) {
|
||||
// tZ -= offset;
|
||||
// } else if (rightJoy.v >= 200) {
|
||||
// tZ += offset;
|
||||
// }
|
||||
|
||||
// if (pad->getPressed().Circle) {
|
||||
// tX -= offset;
|
||||
// } else if (pad->getPressed().Cross) {
|
||||
// tX += offset;
|
||||
// }
|
||||
|
||||
// mesh->rotation.identity();
|
||||
// mesh->rotation.rotateY(rY);
|
||||
// mesh->rotation.rotateZ(rZ);
|
||||
|
||||
// mesh->translation.identity();
|
||||
// mesh->translation.translateX(tX);
|
||||
// mesh->translation.translateY(tY);
|
||||
// mesh->translation.translateZ(tZ);
|
||||
|
||||
// TYRA_LOG("tX: ", tX, " tY: ", tY, " tZ: ", tZ, " rY: ", rY, " rZ: ", rZ);
|
||||
// }
|
||||
|
||||
void Weapon::allocateOptions() {
|
||||
options = new StaPipOptions();
|
||||
options->textureMappingType = Tyra::TyraNearest;
|
||||
|
||||
Reference in New Issue
Block a user