Merge pull request #47 from h4570/samples/floors

Floors sample rework
This commit is contained in:
Sandro Sobczyński
2020-12-08 08:15:52 +01:00
committed by GitHub
17 changed files with 660 additions and 192 deletions
+2
View File
@@ -6,8 +6,10 @@ EE_OBJS = \
managers/light_manager.o \ managers/light_manager.o \
managers/floor_manager.o \ managers/floor_manager.o \
camera.o \ camera.o \
objects/enemy.o \
objects/floor.o \ objects/floor.o \
objects/player.o \ objects/player.o \
ui.o \
utils.o \ utils.o \
floors.o \ floors.o \
main.o main.o
+2 -13
View File
@@ -48,10 +48,10 @@ void Camera::update(Pad &t_pad, Mesh &t_mesh)
*/ */
void Camera::rotate(Pad &t_pad) void Camera::rotate(Pad &t_pad)
{ {
if (t_pad.rJoyH <= 50) if (t_pad.rJoyH <= 100)
horizontalLevel -= 0.08; horizontalLevel -= 0.08;
else if (t_pad.rJoyH >= 200) else if (t_pad.rJoyH >= 200)
horizontalLevel += 0.04; horizontalLevel += 0.08;
if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F) if (t_pad.rJoyV <= 50 && verticalLevel > 25.0F)
verticalLevel -= 0.9F; verticalLevel -= 0.9F;
else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F) else if (t_pad.rJoyV >= 200 && verticalLevel < 80.0F)
@@ -67,15 +67,4 @@ void Camera::followBy(Mesh &t_mesh)
position.x = unitCirclePosition.x + t_mesh.position.x; position.x = unitCirclePosition.x + t_mesh.position.x;
position.y = unitCirclePosition.y + t_mesh.position.y; position.y = unitCirclePosition.y + t_mesh.position.y;
position.z = unitCirclePosition.z + t_mesh.position.z; position.z = unitCirclePosition.z + t_mesh.position.z;
if (position.x > (-0.04F * verticalLevel) &&
position.x < 0.0F &&
position.z > (0.998F * verticalLevel))
{
// TODO
// position.x = 0.0F;
// position.y = 0.0F;
// position.z = 0.0F;
// horizontalLevel = 0.0F;
}
} }
+42 -20
View File
@@ -14,15 +14,22 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
const u8 FLOORS_COUNT = 144; // Temp change it also in floor_manager.hpp const u16 FLOORS_COUNT = 144; // Temp change it also in floor_manager.hpp
Floors::Floors(Engine *t_engine) Floors::Floors(Engine *t_engine)
: engine(t_engine), floorManager(FLOORS_COUNT), camera(&t_engine->screen) : engine(t_engine), floorManager(), camera(&t_engine->screen)
{ {
audioTicks = 0; audioTicks = 0;
skip1Beat = 0;
} }
Floors::~Floors() {} Floors::~Floors()
{
delete enemy;
delete ui;
delete floorManager;
delete player;
}
// ---- // ----
// Methods // Methods
@@ -30,43 +37,58 @@ Floors::~Floors() {}
void Floors::onInit() void Floors::onInit()
{ {
setBgColorAndAmbientColor();
engine->renderer->setCameraDefinitions(&camera.worldView, &camera.unitCirclePosition, camera.planes); engine->renderer->setCameraDefinitions(&camera.worldView, &camera.unitCirclePosition, camera.planes);
engine->audio.addSongListener(this); engine->audio.addSongListener(this);
engine->audio.loadSong("NF-CHILL.WAV"); engine->audio.loadSong("sounds/mafikizolo-loot.wav");
engine->audio.setSongVolume(100);
engine->audio.playSong(); engine->audio.playSong();
engine->audio.setSongVolume(80);
texRepo = engine->renderer->getTextureRepository(); texRepo = engine->renderer->getTextureRepository();
texRepo->addByMesh("warrior/", player.mesh, BMP); enemy = new Enemy(texRepo);
texRepo->addByMesh("floor/", floorManager.floors[0].mesh, BMP); ui = new Ui(texRepo);
for (u32 i = 1; i < floorManager.floorAmount; i++) floorManager = new FloorManager(FLOORS_COUNT, texRepo);
texRepo->getByMesh(floorManager.floors[0].mesh.getId(), floorManager.floors[0].mesh.getMaterial(0).getId()) player = new Player(&engine->audio, texRepo);
->addLink(floorManager.floors[i].mesh.getId(), floorManager.floors[i].mesh.getMaterial(0).getId());
} }
void Floors::onUpdate() void Floors::onUpdate()
{ {
if (engine->pad.isCrossClicked) ui->update(*player);
printf("FPS:%f\n", engine->fps); enemy->update(*floorManager);
lightManager.update(); lightManager.update();
camera.update(engine->pad, player.mesh); camera.update(engine->pad, player->mesh);
floorManager.update(player); floorManager->update(*player);
player.update(engine->pad, camera, floorManager); player->update(engine->pad, camera, *floorManager, *enemy);
engine->renderer->draw(player.mesh); engine->renderer->draw(player->mesh);
for (u8 i = 0; i < FLOORS_COUNT; i++) engine->renderer->draw(enemy->getMeshes(), enemy->getMeshesCount());
engine->renderer->drawByPath3(floorManager.floors[i].mesh, lightManager.bulbs, lightManager.bulbsCount); for (u16 i = 0; i < FLOORS_COUNT; i++)
engine->renderer->drawByPath3(floorManager->floors[i].mesh, lightManager.bulbs, lightManager.bulbsCount);
ui->render(engine->renderer); // 2D rendering ist LAST step, because layers gonna play there.
} }
void Floors::onAudioTick() void Floors::onAudioTick()
{ {
if ((++audioTicks + 20) % 41 == 0) if ((++audioTicks + 20) % 21 == 0)
{ {
floorManager.onAudioTick(); if (skip1Beat)
floorManager->onAudioTick();
lightManager.onAudioTick(); lightManager.onAudioTick();
skip1Beat = !skip1Beat;
} }
if (audioTicks > 10000) if (audioTicks > 10000)
audioTicks = 0; audioTicks = 0;
} }
void Floors::setBgColorAndAmbientColor()
{
color_t bgColor;
bgColor.r = 0x20;
bgColor.g = 0x20;
bgColor.b = 0x20;
engine->renderer->setWorldColor(bgColor);
Vector3 ambient = Vector3(0.003F, 0.003F, 0.003F);
engine->renderer->setAmbientLight(ambient);
}
void Floors::onAudioFinish() void Floors::onAudioFinish()
{ {
audioTicks = 0; audioTicks = 0;
+8 -2
View File
@@ -18,7 +18,9 @@
#include "managers/light_manager.hpp" #include "managers/light_manager.hpp"
#include "modules/texture_repository.hpp" #include "modules/texture_repository.hpp"
#include "objects/player.hpp" #include "objects/player.hpp"
#include "objects/enemy.hpp"
#include "./camera.hpp" #include "./camera.hpp"
#include "./ui.hpp"
class Floors : public Game, AudioListener class Floors : public Game, AudioListener
{ {
@@ -35,12 +37,16 @@ public:
Engine *engine; Engine *engine;
private: private:
void setBgColorAndAmbientColor();
u32 audioTicks; u32 audioTicks;
u8 skip1Beat;
TextureRepository *texRepo; TextureRepository *texRepo;
LightManager lightManager; LightManager lightManager;
FloorManager floorManager; FloorManager *floorManager;
Player player; Player *player;
Camera camera; Camera camera;
Ui *ui;
Enemy *enemy;
}; };
#endif #endif
+78 -14
View File
@@ -20,13 +20,18 @@
/** Calculate square spiral offsets and initialize floors /** Calculate square spiral offsets and initialize floors
* @param floorAmount must be a number from square root table * @param floorAmount must be a number from square root table
*/ */
FloorManager::FloorManager(int t_floorAmount) FloorManager::FloorManager(int t_floorAmount, TextureRepository *t_texRepo)
{ {
texRepo = t_texRepo;
floorAmount = t_floorAmount; floorAmount = t_floorAmount;
spirals = new Point[t_floorAmount]; spirals = new Point[t_floorAmount];
int floorSpiralMaxOffset = (int)Math::sqrt(t_floorAmount); int floorSpiralMaxOffset = (int)Math::sqrt(t_floorAmount);
calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset); calcSpiral(floorSpiralMaxOffset, floorSpiralMaxOffset);
initFloors(); initFloors();
trick = 0.0F;
trickMode = 0;
isTimeForChangeTriggerColor = true;
isTimeForChangeDefaultColor = true;
audioOffset = audioMode = audioTick = 0; audioOffset = audioMode = audioTick = 0;
} }
@@ -77,11 +82,16 @@ void FloorManager::calcSpiral(int X, int Y)
void FloorManager::initFloors() void FloorManager::initFloors()
{ {
PRINT_LOG("Initializing floors"); PRINT_LOG("Initializing floors");
floors[0].mesh.loadObj("floor/", "floor", 3.0F, false); floors[0].mesh.loadObj("meshes/floor/", "floor", 3.0F, false);
floors[0].mesh.shouldBeFrustumCulled = true; floors[0].mesh.shouldBeFrustumCulled = true;
floors[0].mesh.shouldBeLighted = true; floors[0].mesh.shouldBeLighted = true;
for (u8 i = 1; i < floorAmount; i++) texRepo->addByMesh("meshes/floor/", floors[0].mesh, BMP);
for (u16 i = 1; i < floorAmount; i++)
{
floors[i].init(floors[0].mesh, spirals[i], i); floors[i].init(floors[0].mesh, spirals[i], i);
texRepo->getByMesh(floors[0].mesh.getId(), floors[0].mesh.getMaterial(0).getId())
->addLink(floors[i].mesh.getId(), floors[i].mesh.getMaterial(0).getId());
}
PRINT_LOG("Floors initialized!"); PRINT_LOG("Floors initialized!");
} }
@@ -92,25 +102,75 @@ void FloorManager::initFloors()
*/ */
void FloorManager::update(Player &t_player) void FloorManager::update(Player &t_player)
{ {
for (u8 i = 0; i < floorAmount; i++) if (isTimeForChangeTriggerColor)
{
isTimeForChangeTriggerColor = false;
trigColor.r = rand() % (128 - 64 + 1) + 64;
trigColor.g = rand() % (128 - 64 + 1) + 64;
trigColor.b = rand() % (128 - 64 + 1) + 64;
}
if (isTimeForChangeDefaultColor)
{
isTimeForChangeDefaultColor = false;
defaultColor.r = rand() % (64 + 1);
defaultColor.g = rand() % (64 + 1);
defaultColor.b = rand() % (64 + 1);
}
doTheTrick();
for (u16 i = 0; i < floorAmount; i++)
{ {
floors[i].animate(t_player); floors[i].animate(t_player);
if (floors[i].isByAudioTriggered == true) if (floors[i].isByAudioTriggered)
floors[i].mesh.color.a = 0x20; {
else floors[i].mesh.color.r = trigColor.r;
floors[i].mesh.color.a = 0x80; floors[i].mesh.color.g = trigColor.g;
floors[i].mesh.color.b = trigColor.b;
} }
else
{
floors[i].mesh.color.r = defaultColor.r;
floors[i].mesh.color.g = defaultColor.g;
floors[i].mesh.color.b = defaultColor.b;
}
}
}
void FloorManager::doTheTrick()
{
if (trickMode == 0)
{
if (trick > 3.0F)
{
isTimeForChangeTriggerColor = true;
trickMode = 1;
}
trick += 0.01F;
}
else if (trickMode == 1)
{
if (trick <= 0.1F)
{
isTimeForChangeTriggerColor = true;
trickMode = 0;
}
trick -= 0.01F;
}
floors[0].mesh.getFrames()[0].getST(1).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(4).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(7).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(10).set(trick, trick);
floors[0].mesh.getFrames()[0].getST(13).set(trick, trick);
} }
/** Called by audio thread */ /** Called by audio thread */
void FloorManager::onAudioTick() void FloorManager::onAudioTick()
{ {
if (audioTick++ > 16) if (audioTick++ > 19)
{ {
if (audioMode == 0) if (audioMode == 0)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if ((i + audioOffset) % 2 == 0) if ((i + audioOffset) % 2 == 0)
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
@@ -120,12 +180,13 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 1; audioMode = 1;
} }
} }
else if (audioMode == 1) else if (audioMode == 1)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if (i < floorAmount / (audioOffset + 1)) if (i < floorAmount / (audioOffset + 1))
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
@@ -135,12 +196,13 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 2; audioMode = 2;
} }
} }
else if (audioMode == 2) else if (audioMode == 2)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if ((i + audioOffset) % 4 == 0) if ((i + audioOffset) % 4 == 0)
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
@@ -150,14 +212,15 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 3; audioMode = 3;
} }
} }
else if (audioMode == 3) else if (audioMode == 3)
{ {
for (u8 i = 0; i < floorAmount; i++) for (u16 i = 0; i < floorAmount; i++)
{ {
if (u8(i + 1) > floorAmount / (audioOffset + 1)) if (u16(i + 1) > floorAmount / (audioOffset + 1))
floors[i].isByAudioTriggered = true; floors[i].isByAudioTriggered = true;
else else
floors[i].isByAudioTriggered = false; floors[i].isByAudioTriggered = false;
@@ -165,6 +228,7 @@ void FloorManager::onAudioTick()
if (++audioOffset > 3) if (++audioOffset > 3)
{ {
audioOffset = 0; audioOffset = 0;
isTimeForChangeDefaultColor = true;
audioMode = 0; audioMode = 0;
} }
} }
@@ -14,6 +14,7 @@
class Player; // Forward definition class Player; // Forward definition
#include <models/math/point.hpp> #include <models/math/point.hpp>
#include <modules/texture_repository.hpp>
#include <modules/camera_base.hpp> #include <modules/camera_base.hpp>
#include <models/audio_listener.hpp> #include <models/audio_listener.hpp>
@@ -24,18 +25,24 @@ class FloorManager
{ {
public: public:
FloorManager(int t_floorAmount); FloorManager(int t_floorAmount, TextureRepository *t_texRepo);
~FloorManager(); ~FloorManager();
Floor floors[144]; // Temp change it also in floors.cpp Floor floors[144]; // Temp change it also in floors.cpp
u32 floorAmount; u16 floorAmount;
void update(Player &t_player); void update(Player &t_player);
void onAudioTick(); void onAudioTick();
private: private:
TextureRepository *texRepo;
u8 audioOffset, audioMode; u8 audioOffset, audioMode;
u32 audioTick; u32 audioTick;
float trick;
u8 isTimeForChangeTriggerColor, isTimeForChangeDefaultColor;
color_t trigColor, defaultColor;
u8 trickMode;
Point *spirals; Point *spirals;
void calcSpiral(int X, int Y); void calcSpiral(int X, int Y);
void doTheTrick();
void initFloors(); void initFloors();
}; };
@@ -142,7 +142,7 @@ void LightManager::onAudioTick()
} }
else else
{ {
bulbs[0].intensity += 6; bulbs[0].intensity += 9;
bulbs[1].intensity += 6; bulbs[1].intensity += 9;
} }
} }
+103
View File
@@ -0,0 +1,103 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "enemy.hpp"
#include "../utils.hpp"
#include <loaders/md2_loader.hpp>
#include <loaders/bmp_loader.hpp>
#include <modules/gif_sender.hpp>
#include <utils/debug.hpp>
#include <utils/math.hpp>
// ----
// Constructors/Destructors
// ----
Enemy::Enemy(TextureRepository *t_texRepo)
{
PRINT_LOG("Creating enemy object");
meshes = new Mesh[getMeshesCount()];
meshes[0].loadMD2("meshes/enemy/", "poss_head", 0.3F, false);
meshes[0].rotation.x = -1.566F;
meshes[0].rotation.z = 1.566F;
meshes[1].loadMD2("meshes/enemy/", "poss_body", 0.3F, false);
meshes[1].rotation.x = -1.566F;
meshes[1].rotation.z = 1.566F;
meshes[2].loadMD2("meshes/enemy/", "poss_weapon", 0.3F, false);
meshes[2].rotation.x = -1.566F;
meshes[2].rotation.z = 1.566F;
Vector3 initPos = Vector3(0.00F, 40.00F, 0.00F);
setPosition(initPos);
t_texRepo->addByMesh("meshes/enemy/", meshes[0], PNG);
t_texRepo->addByMesh("meshes/enemy/", meshes[1], PNG);
t_texRepo->addByMesh("meshes/enemy/", meshes[2], PNG);
meshes[0].playAnimation(1, 6);
meshes[1].playAnimation(1, 6);
meshes[2].playAnimation(1, 6);
isKilled = true;
PRINT_LOG("Enemy object created!");
}
Enemy::~Enemy()
{
delete[] meshes;
}
// ----
// Methods
// ----
void Enemy::setPosition(const Vector3 &t_vec)
{
position.set(t_vec);
for (u8 i = 0; i < getMeshesCount(); i++)
meshes[i].position.set(t_vec);
}
void Enemy::setPosition(const float &t_y)
{
position.y = t_y;
for (u8 i = 0; i < getMeshesCount(); i++)
meshes[i].position.y = t_y;
}
/** Called by player class. */
void Enemy::kill(const Player &player)
{
isKilled = true;
}
void Enemy::update(const FloorManager &floorManager)
{
if (isKilled)
{
isKilled = false;
int randFloor = rand() % (floorManager.floorAmount + 1);
currentFloor = &floorManager.floors[randFloor];
setPosition(currentFloor->mesh.position);
}
updateGravity();
}
void Enemy::updateGravity()
{
Utils::getMinMax(currentFloor->mesh, currFloorMin, currFloorMax);
setPosition(currFloorMax.y);
}
+44
View File
@@ -0,0 +1,44 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _ENEMY_
#define _ENEMY_
#include <tamtypes.h>
#include "../managers/floor_manager.hpp"
#include <modules/texture_repository.hpp>
/** Player 3D object class */
class Enemy
{
public:
s16 indexOfCurrentFloor;
Enemy(TextureRepository *t_texRepo);
~Enemy();
inline Mesh *getMeshes() const { return meshes; }
inline u8 getMeshesCount() const { return 3; }
inline Vector3 getPosition() const { return position; }
void setPosition(const Vector3 &t_vec);
void setPosition(const float &t_y);
void kill(const Player &player);
void update(const FloorManager &t_floorManager);
private:
/** 0 - head, 1 - body, 2 - weapon */
Mesh *meshes;
const Floor *currentFloor;
Vector3 position, currFloorMin, currFloorMax;
u8 isKilled;
void updateGravity();
};
#endif
+7 -7
View File
@@ -23,7 +23,13 @@ const float FLOOR_ANIMATION_Y_MAX = 10.0F;
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Floor::Floor() {} Floor::Floor()
{
animTimer = 0;
animDirection = 0;
initOffset = 0;
isByAudioTriggered = false;
}
Floor::~Floor() {} Floor::~Floor() {}
@@ -31,11 +37,6 @@ Floor::~Floor() {}
// Methods // Methods
// ---- // ----
/** Init floor position and animation timer position
* @param spec pointer to 3D object specification
* @param spiral Spiral position
* @param initOffset Number of floor (index)
*/
void Floor::init(const Mesh &mother, const Point &spiral, const u8 &initOffset) void Floor::init(const Mesh &mother, const Point &spiral, const u8 &initOffset)
{ {
this->mesh.position.set(0.00F, -10.00F, 0.00F); this->mesh.position.set(0.00F, -10.00F, 0.00F);
@@ -44,7 +45,6 @@ void Floor::init(const Mesh &mother, const Point &spiral, const u8 &initOffset)
this->animTimer = rand() % FLOOR_ANIMATION_LENGTH; this->animTimer = rand() % FLOOR_ANIMATION_LENGTH;
this->mesh.shouldBeLighted = true; this->mesh.shouldBeLighted = true;
this->mesh.shouldBeFrustumCulled = true; this->mesh.shouldBeFrustumCulled = true;
this->animDirection = 0;
this->mesh.position.x = spiral.x * 80.0F; this->mesh.position.x = spiral.x * 80.0F;
this->mesh.position.z = spiral.y * 80.0F; this->mesh.position.z = spiral.y * 80.0F;
} }
+1 -1
View File
@@ -23,7 +23,7 @@ class Floor
public: public:
u16 animTimer; u16 animTimer;
u8 animDirection, initOffset, isByAudioTriggered; s16 animDirection, initOffset, isByAudioTriggered;
Mesh mesh; Mesh mesh;
Floor(); Floor();
+171 -124
View File
@@ -9,8 +9,9 @@
*/ */
#include "player.hpp" #include "player.hpp"
#include "../utils.hpp"
#include <loaders/obj_loader.hpp> #include <loaders/md2_loader.hpp>
#include <loaders/bmp_loader.hpp> #include <loaders/bmp_loader.hpp>
#include <modules/gif_sender.hpp> #include <modules/gif_sender.hpp>
#include <utils/debug.hpp> #include <utils/debug.hpp>
@@ -20,20 +21,38 @@
// Constructors/Destructors // Constructors/Destructors
// ---- // ----
Player::Player() Player::Player(Audio *t_audio, TextureRepository *t_texRepo)
{ {
PRINT_LOG("Creating player object"); PRINT_LOG("Creating player object");
this->gravity = 0.1F; texRepo = t_texRepo;
this->lift = -1.0F; audio = t_audio;
gravity = 0.1F;
lift = -1.0F;
jumpCounter = 0;
speed = 1.0F;
killedEnemies = 0;
isWalking = false;
isFighting = false;
isWalkingAnimationSet = false;
isJumpingAnimationSet = false;
isFightingAnimationSet = false;
this->mesh.loadMD2("warrior/", "warrior", 0.2F, true); mesh.loadMD2("meshes/player/", "warrior", 0.2F, true);
this->mesh.position.set(0.00F, 20.00F, 0.00F); mesh.position.set(0.00F, 40.00F, 0.00F);
this->mesh.rotation.x = -1.6F; mesh.rotation.x = -1.566F;
this->mesh.shouldBeBackfaceCulled = false; mesh.rotation.z = 1.566F;
this->mesh.shouldBeFrustumCulled = false; mesh.shouldBeBackfaceCulled = false;
mesh.shouldBeFrustumCulled = false;
mesh.setAnimSpeed(0.17F);
mesh.playAnimation(0, 0);
texRepo->addByMesh("meshes/player/", mesh, BMP);
walkAdpcm = audio->loadADPCM("sounds/walk.adpcm");
jumpAdpcm = audio->loadADPCM("sounds/jump.adpcm");
boomAdpcm = audio->loadADPCM("sounds/boom.adpcm");
audio->setADPCMVolume(70, 0);
this->mesh.setAnimSpeed(0.2F);
this->mesh.playAnimation(0, 24);
PRINT_LOG("Player object created!"); PRINT_LOG("Player object created!");
} }
@@ -45,139 +64,167 @@ Player::~Player()
// Methods // Methods
// ---- // ----
/** Update player position and control gravity */ void Player::update(const Pad &t_pad, const Camera &t_camera, const FloorManager &floorManager, Enemy &enemy)
void Player::update(Pad &pad, Camera &camera, FloorManager &floorManager)
{ {
this->updatePosition(pad, camera, floorManager); Vector3 *nextPos = getNextPosition(t_pad, t_camera);
this->updateGravity(pad, floorManager); FloorsCheck *floorsCheck = checkFloors(floorManager, *nextPos);
if (mesh.position.y < -60.0F) if (floorsCheck->currentFloor != NULL)
indexOfCurrentFloor = floorsCheck->currentFloor->initOffset;
updatePosition(t_pad, t_camera, floorManager, *floorsCheck, *nextPos, enemy);
updateGravity(floorsCheck);
delete floorsCheck;
delete nextPos;
}
Vector3 *Player::getNextPosition(const Pad &t_pad, const Camera &t_camera)
{
Vector3 *result = new Vector3(mesh.position);
Vector3 normalizedCamera = Vector3(t_camera.unitCirclePosition);
normalizedCamera.normalize();
normalizedCamera *= speed;
if (t_pad.lJoyV <= 100)
{ {
mesh.position.y = 60.0F; result->x += -normalizedCamera.x;
velocity = 0; result->z += -normalizedCamera.z;
}
else if (t_pad.lJoyV >= 200)
{
result->x += normalizedCamera.x;
result->z += normalizedCamera.z;
}
if (t_pad.lJoyH <= 100)
{
result->x += -normalizedCamera.z;
result->z += normalizedCamera.x;
}
else if (t_pad.lJoyH >= 200)
{
result->x += normalizedCamera.z;
result->z += -normalizedCamera.x;
}
return result;
}
void Player::updatePosition(const Pad &t_pad, const Camera &t_camera, const FloorManager &t_floorManager, const FloorsCheck &t_floorsCheck, const Vector3 &t_nextPos, Enemy &enemy)
{
if (t_pad.rJoyH >= 200)
mesh.rotation.z += 0.08;
else if (t_pad.rJoyH <= 100)
mesh.rotation.z -= 0.08;
isWalking = mesh.position.x != t_nextPos.x || mesh.position.z != t_nextPos.z;
isFighting = isFighting || t_pad.isCircleClicked;
if (isFighting)
{
if (!isFightingAnimationSet)
{
isFightingAnimationSet = true;
mesh.playAnimation(8, 19, 0);
fightTimer.prime();
}
if (fightTimer.getTimeDelta() > 25000)
{ // end of fighting
float distance = getPosition().distanceTo(enemy.getPosition());
if (16.0F > distance)
{
enemy.kill(*this);
audio->playADPCM(boomAdpcm);
speed += .5F;
killedEnemies++;
}
isFightingAnimationSet = false;
isFighting = false;
}
}
else if (isWalking)
{
if (!isWalkingAnimationSet)
{
isWalkingAnimationSet = true;
this->mesh.playAnimation(1, 8);
}
if (walkTimer.getTimeDelta() > 8000)
{
walkTimer.prime();
audio->playADPCM(walkAdpcm, 0);
}
}
else
{
isWalkingAnimationSet = false;
mesh.playAnimation(0, 0);
}
if (t_floorsCheck.willCollideFloor == NULL && !isFighting)
{
mesh.position.x = t_nextPos.x;
mesh.position.z = t_nextPos.z;
}
if (t_pad.isCrossClicked == 1)
{
velocity = lift;
audio->playADPCM(jumpAdpcm);
jumpCounter++;
} }
} }
/** Move player when pad move buttons are pressed and is not blocked by any floor side */ /**
void Player::updatePosition(Pad &pad, Camera &camera, FloorManager &floorManager) * Do not call this.
{
if (pad.isDpadUpPressed == 1)
{
this->playerNextPosition.x = this->mesh.position.x + 0.01F * -camera.unitCirclePosition.x;
this->playerNextPosition.z = this->mesh.position.z + 0.01F * -camera.unitCirclePosition.z;
}
if (pad.isDpadDownPressed == 1)
{
this->playerNextPosition.x = this->mesh.position.x + 0.01F * camera.unitCirclePosition.x;
this->playerNextPosition.z = this->mesh.position.z + 0.01F * camera.unitCirclePosition.z;
}
if (pad.isDpadLeftPressed == 1)
{
this->playerNextPosition.x = this->mesh.position.x + 0.01F * -camera.unitCirclePosition.z;
this->playerNextPosition.z = this->mesh.position.z + 0.01F * camera.unitCirclePosition.x;
}
if (pad.isDpadRightPressed == 1)
{
this->playerNextPosition.x = this->mesh.position.x + 0.01F * camera.unitCirclePosition.z;
this->playerNextPosition.z = this->mesh.position.z + 0.01F * -camera.unitCirclePosition.x;
}
this->playerNextPosition.y = this->mesh.position.y;
this->isCollideFloor = 0;
Vector3 min = Vector3();
Vector3 max = Vector3();
for (u32 i = 0; i < floorManager.floorAmount; i++)
{
getMinMax(&floorManager.floors[i].mesh, &min, &max);
this->isCollideFloor = this->playerNextPosition.collidesSquare(min, max);
if (this->isCollideFloor == 1)
break;
}
if (this->isCollideFloor == 0)
{
this->mesh.position.x = this->playerNextPosition.x;
this->mesh.position.z = this->playerNextPosition.z;
}
}
/** Do not call this.
* This is called by Floor::animate() on player's floor move in Y direction * This is called by Floor::animate() on player's floor move in Y direction
*/ */
void Player::onBeforePlayerFloorMove(Floor *floor, float &newY) void Player::onBeforePlayerFloorMove(Floor *t_floor, float &t_newY)
{ {
if (floor->animDirection == 0 && newY > 0.0F) if (t_floor->animDirection == 0 && t_newY > 0.0F)
this->mesh.position.y += newY * 1.05F; this->mesh.position.y += t_newY * 1.05F;
else if ((floor->animDirection == 1 && -newY < 0.0F)) else if ((t_floor->animDirection == 1 && -t_newY < 0.0F))
this->mesh.position.y -= -newY * 1.05F; this->mesh.position.y -= -t_newY * 1.05F;
}
/** Calculates minimum and maximum X, Y, Z of mesh vertices + current position */
void Player::getMinMax(Mesh *t_mesh, Vector3 *t_min, Vector3 *t_max)
{
Vector3 calc = Vector3();
u8 isInitialized = 0;
Vector3 *boundingBox = t_mesh->getCurrentBoundingBox();
for (u32 i = 0; i < 8; i++)
{
calc.set(
boundingBox[i].x + t_mesh->position.x,
boundingBox[i].y + t_mesh->position.y,
boundingBox[i].z + t_mesh->position.z);
if (isInitialized == 0)
{
isInitialized = 1;
t_min->set(calc);
t_max->set(calc);
}
if (t_min->x > calc.x)
t_min->x = calc.x;
if (calc.x > t_max->x)
t_max->x = calc.x;
if (t_min->y > calc.y)
t_min->y = calc.y;
if (calc.y > t_max->y)
t_max->y = calc.y;
if (t_min->z > calc.z)
t_min->z = calc.z;
if (calc.z > t_max->z)
t_max->z = calc.z;
}
} }
/** Update player position by gravity and update index of current floor */ /** Update player position by gravity and update index of current floor */
void Player::updateGravity(Pad &pad, FloorManager &floorManager) void Player::updateGravity(FloorsCheck *t_floorsCheck)
{ {
Vector3 min = Vector3();
Vector3 max = Vector3();
if (pad.isCrossClicked == 1)
this->velocity = this->lift;
this->isOnFloor = 0;
for (u32 i = 0; i < floorManager.floorAmount; i++)
{
getMinMax(&floorManager.floors[i].mesh, &min, &max);
this->isOnFloor = this->mesh.position.isOnSquare(min, max);
if (this->isOnFloor == 1)
{
this->indexOfCurrentFloor = floorManager.floors[i].initOffset;
break;
}
}
this->velocity += this->gravity; this->velocity += this->gravity;
this->mesh.position.y -= this->velocity; this->mesh.position.y -= this->velocity;
u8 isOnFloor = t_floorsCheck->currentFloor != NULL && mesh.position.y < t_floorsCheck->currFloorMax.y;
if (this->mesh.position.y >= 60.0F) if (this->mesh.position.y >= 60.0F || mesh.position.y < -60.0F)
{ {
this->mesh.position.y = 60.0F; this->mesh.position.y = 60.0F;
this->velocity = 0; this->velocity = 0;
} }
else if ((this->mesh.position.y) < max.y && this->isOnFloor) else if (isOnFloor)
{ {
this->mesh.position.y = max.y; this->mesh.position.y = t_floorsCheck->currFloorMax.y;
this->velocity = 0; this->velocity = 0;
} }
} }
FloorsCheck *Player::checkFloors(const FloorManager &t_floorManager, const Vector3 &t_nextPos)
{
FloorsCheck *result = new FloorsCheck;
result->currentFloor = NULL;
result->willCollideFloor = NULL;
Vector3 min = Vector3();
Vector3 max = Vector3();
for (u32 i = 0; i < t_floorManager.floorAmount; i++)
{
Utils::getMinMax(t_floorManager.floors[i].mesh, min, max);
if (result->currentFloor == NULL && this->mesh.position.isOnSquare(min, max))
{
result->currentFloor = &t_floorManager.floors[i];
result->currFloorMin.set(min);
result->currFloorMax.set(max);
}
if (result->willCollideFloor == NULL && t_nextPos.collidesSquare(min, max))
{
result->willCollideFloor = &t_floorManager.floors[i];
result->willCollideFloorMin.set(min);
result->willCollideFloorMax.set(max);
}
if (result->currentFloor != NULL && result->willCollideFloor != NULL)
break;
}
return result;
}
+29 -8
View File
@@ -13,8 +13,17 @@
#include "../managers/floor_manager.hpp" #include "../managers/floor_manager.hpp"
#include "../camera.hpp" #include "../camera.hpp"
#include "./enemy.hpp"
#include <modules/pad.hpp> #include <modules/pad.hpp>
#include <modules/timer.hpp>
#include <tamtypes.h> #include <tamtypes.h>
#include <modules/audio.hpp>
struct FloorsCheck
{
const Floor *currentFloor, *willCollideFloor;
Vector3 currFloorMin, willCollideFloorMin, currFloorMax, willCollideFloorMax;
};
/** Player 3D object class */ /** Player 3D object class */
class Player class Player
@@ -22,19 +31,31 @@ class Player
public: public:
float gravity, velocity, lift; float gravity, velocity, lift;
u8 isOnFloor, isCollideFloor, indexOfCurrentFloor;
Mesh mesh; Mesh mesh;
Player(); s16 indexOfCurrentFloor;
Player(Audio *t_audio, TextureRepository *t_texRepo);
~Player(); ~Player();
void update(Pad &pad, Camera &camera, FloorManager &floorManager); void update(const Pad &t_pad, const Camera &t_camera, const FloorManager &t_floorManager, Enemy &enemy);
void onBeforePlayerFloorMove(Floor *floor, float &newY); void onBeforePlayerFloorMove(Floor *t_floor, float &t_newY);
const inline u32 &getJumpCount() const { return jumpCounter; }
const inline u32 &getKilledEnemiesCount() const { return killedEnemies; }
inline const Vector3 &getPosition() const { return mesh.position; }
private: private:
Vector3 playerNextPosition; TextureRepository *texRepo;
void getMinMax(Mesh *t_mesh, Vector3 *t_min, Vector3 *t_max); u32 jumpCounter, killedEnemies;
void updatePosition(Pad &pad, Camera &camera, FloorManager &floorManager); Vector3 *getNextPosition(const Pad &t_pad, const Camera &t_camera);
void updateGravity(Pad &pad, FloorManager &floorManager); FloorsCheck *checkFloors(const FloorManager &t_floorManager, const Vector3 &t_nextPos);
u8 isWalkingAnimationSet, isJumpingAnimationSet, isFightingAnimationSet;
u8 isFighting, isWalking;
Audio *audio;
Timer walkTimer, fightTimer;
audsrv_adpcm_t *walkAdpcm, *jumpAdpcm, *boomAdpcm;
float speed;
void getMinMax(const Mesh &t_mesh, Vector3 &t_min, Vector3 &t_max);
void updatePosition(const Pad &t_pad, const Camera &t_camera, const FloorManager &t_floorManager, const FloorsCheck &t_floorsCheck, const Vector3 &nextPos, Enemy &enemy);
void updateGravity(FloorsCheck *t_floorsCheck);
}; };
#endif #endif
+89
View File
@@ -0,0 +1,89 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#include "ui.hpp"
#include <utils/debug.hpp>
// ----
// Constructors/Destructors
// ----
Ui::Ui(TextureRepository *t_texRepo)
{
PRINT_LOG("Initializing ui");
isTask1Done = false;
isTask2Done = false;
info.size.set(128.0F, 32.0F);
info.position.set(500.0F, 430.0F);
reward.size.set(128.0F, 128.0F);
reward.position.set(500.0F, 280.0F);
reward.flipVertically(true);
task1.size.set(128.0F, 32.0F);
task1.position.set(500.0F, 10.0F);
task2.size.set(128.0F, 32.0F);
task2.position.set(500.0F, 50.0F);
task1Checkbox.size.set(32.0F, 32.0F);
task1Checkbox.position.set(460.0F, 10.0F);
task2Checkbox.size.set(32.0F, 32.0F);
task2Checkbox.position.set(460.0F, 50.0F);
t_texRepo->add("ui/", "reward", BMP)->addLink(reward.getId());
t_texRepo->add("ui/", "info-text", PNG)->addLink(info.getId());
t_texRepo->add("ui/", "check1-text", PNG)->addLink(task1.getId());
t_texRepo->add("ui/", "check2-text", PNG)->addLink(task2.getId());
grayCheckboxTex = t_texRepo->add("ui/", "gray-checkmark", PNG);
blueCheckboxTex = t_texRepo->add("ui/", "blue-checkmark", PNG);
grayCheckboxTex->addLink(task1Checkbox.getId());
grayCheckboxTex->addLink(task2Checkbox.getId());
PRINT_LOG("Ui initialized!");
}
Ui::~Ui() {}
// ----
// Methods
// ----
void Ui::update(const Player &player)
{
if (!isTask1Done && player.getJumpCount() >= 10)
{
isTask1Done = true;
grayCheckboxTex->removeLinkBySprite(task1Checkbox.getId());
blueCheckboxTex->addLink(task1Checkbox.getId());
}
if (!isTask2Done && player.getKilledEnemiesCount() >= 10)
{
isTask2Done = true;
grayCheckboxTex->removeLinkBySprite(task2Checkbox.getId());
blueCheckboxTex->addLink(task2Checkbox.getId());
}
}
void Ui::render(Renderer *t_renderer)
{
if (isTask1Done && isTask2Done)
t_renderer->draw(reward);
t_renderer->draw(info);
t_renderer->draw(task1);
t_renderer->draw(task2);
t_renderer->draw(task1Checkbox);
t_renderer->draw(task2Checkbox);
}
+35
View File
@@ -0,0 +1,35 @@
/*
# ______ ____ ___
# | \/ ____| |___|
# | | | \ | |
#-----------------------------------------------------------------------
# Copyright 2020, tyra - https://github.com/h4570/tyra
# Licenced under Apache License 2.0
# Sandro Sobczyński <sandro.sobczynski@gmail.com>
*/
#ifndef _UI_
#define _UI_
#include <modules/texture_repository.hpp>
#include <modules/renderer.hpp>
#include "objects/player.hpp"
#include <tamtypes.h>
class Ui
{
public:
Ui(TextureRepository *t_texRepo);
~Ui();
void update(const Player &player);
void render(Renderer *t_renderer);
private:
u8 isTask1Done, isTask2Done;
Sprite task1, task2, task1Checkbox, task2Checkbox, info, reward;
Texture *grayCheckboxTex, *blueCheckboxTex;
};
#endif
+36
View File
@@ -32,3 +32,39 @@ float Utils::expoEaseInOut(float t, float b, float c, float d)
return c / 2 * (-powf(2, -10 * --t) + 2) + b; return c / 2 * (-powf(2, -10 * --t) + 2) + b;
} }
/** Calculates minimum and maximum X, Y, Z of mesh vertices + current position */
void Utils::getMinMax(const Mesh &t_mesh, Vector3 &t_min, Vector3 &t_max)
{
Vector3 calc = Vector3();
u8 isInitialized = 0;
Vector3 *boundingBox = t_mesh.getCurrentBoundingBox();
for (u32 i = 0; i < 8; i++)
{
calc.set(
boundingBox[i].x + t_mesh.position.x,
boundingBox[i].y + t_mesh.position.y,
boundingBox[i].z + t_mesh.position.z);
if (isInitialized == 0)
{
isInitialized = 1;
t_min.set(calc);
t_max.set(calc);
}
if (t_min.x > calc.x)
t_min.x = calc.x;
if (calc.x > t_max.x)
t_max.x = calc.x;
if (t_min.y > calc.y)
t_min.y = calc.y;
if (calc.y > t_max.y)
t_max.y = calc.y;
if (t_min.z > calc.z)
t_min.z = calc.z;
if (calc.z > t_max.z)
t_max.z = calc.z;
}
}
+3
View File
@@ -12,12 +12,15 @@
#define _TYRA_UTILS_ #define _TYRA_UTILS_
#include <tamtypes.h> #include <tamtypes.h>
#include <models/mesh.hpp>
#include <models/math/vector3.hpp>
class Utils class Utils
{ {
public: public:
static float expoEaseInOut(float t, float b, float c, float d); static float expoEaseInOut(float t, float b, float c, float d);
static void getMinMax(const Mesh &t_mesh, Vector3 &t_min, Vector3 &t_max);
}; };
#endif #endif