game/Enemy.cpp
#include "SFML-2.5.1\include\SFML\Graphics.hpp"
#include "Enemy.h"
class Enemy
{
public:
Enemy();
~Enemy();
void init(std::string textureName, sf::Vector2f position, float_speed);
void update(float dt);
sf::Sprite getSprite();
private:
sf::Texture m_texture;
sf::Sprite m_sprite;
sf::Vector2f m_position;
float m_speed;
}
Enemy::Enemy(){}
Enemy::~Enemy(){}
void Enemy::init(std::string textureName, sf::Vector2f position, float _speed) {
m_speed = _speed;
m_position = position;
Load a Texture
m_texture.loadFromFile(textureName.c_str());
Create Sprite and Attach a Texture
m_sprite.setTexture(m_texture);
m_sprite.setPosition(m_position);
m_sprite.setOrigin(m_texture.getSize().x / 2,
m_texture.getSize().y / 2);
}
void Enemy::update(float dt) {
m_sprite.move(m_speed * dt, 0);
}
sf::Sprite Enemy::getSprite() {
return m_sprite;
}
game/Enemy_and_hero.cpp
#include "SFML-2.5.1\include\SFML\Graphics.hpp"
#include
#include "Player.h"
#include "Enemy.h"
sf::Texture bgTexture;
sf::Sprite bgSprite;
Player::Player;
std::vecto
Enemy*> enemies;
sf::Vector2f viewSize(1024, 768);
sf::VideoMode vm(viewSize.x, viewSize.y);
sf::RenderWindow window(vm, "Hello SFML Game !!!",
sf::Style::Default);
void spawnEnemy();
player.init("Assets/graphics/hero.png", sf::Vector2f(viewSize.x *
0.25f, viewSize.y * 0.5f), 200);
srand((int)time(0));
void spawnEnemy() {
int randLoc = rand() % 3;
sf::Vector2f enemyPos;
float speed;
switch (randLoc) {
case 0: enemyPos = sf::Vector2f(viewSize.x, viewSize.y * 0.75f);
speed = -400;
eak;
case 1: enemyPos = sf::Vector2f(viewSize.x, viewSize.y * 0.60f);
speed = -550;
eak;
case 2: enemyPos = sf::Vector2f(viewSize.x, viewSize.y * 0.40f);
speed = -650;
eak;
default: printf("inco
ect y value \n"); return;
}
Enemy* enemy = new Enemy();
enemy->init("Assets/graphics/enemy.png", enemyPos, speed);
enemies.push_back(enemy);
}
Player::Player;
std::vecto
Enemy*> enemies;
float cu
entTime;
float prevTime = 0.0f;
Player.update(dt);
cu
entTime += dt;
Spawn Enemies
if (cu
entTime >= prevTime + 1.125f)))) {
spawnEnemy();
prevTime = cu
entTime;
}
Update Enemies
for (int i = 0; i < enemies.size(); i++) {
Enemy *enemy = enemies[i];
enemy->update(dt);
if (enemy->getSprite().getPosition().x < 0) {
enemies.erase(enemies.begin() + i);
delete(enemy);
}
}
window.draw(skySprite);
window.draw(bgSprite);
window.draw(hero.getSprite());
for (Enemy *enemy : enemies) {
window.draw(enemy->getSprite());
}
game/collision.cpp
game/collision.cpp
void spawnEnemy();
void shoot();
ool checkCollision(sf::Sprite sprite1, sf::Sprite sprite2);
void shoot() {
Rocket* rocket = new Rocket();
ocket->init("Assets/graphics
ocket.png",
hero.getSprite().getPosition(), 400.0f);
ockets.push_back(rocket);
}
ool checkCollision(sf::Sprite sprite1, sf::Sprite sprite2) {
sf::FloatRect shape1 = sprite1.getGlobalBounds();
sf::FloatRect shape2 = sprite2.getGlobalBounds();
if (shape1.intersects(shape2)) {
eturn true;
}
else {
eturn false;
}
}
game/field_of_view.cpp
#include
#include
#include
#include
#include
#include
using namespace std;
void GetShortestAngularDisplacement(float first, float second);
void GetShortestAngularDisplacement(float first, float second)
{
180.0 - std::fabs(std::fmod(std::fabs(first - second), 360.0) - 180.0);
}
float GetTurnedToward( float cu
entDegrees, float goalDegrees, float maxDeltaDegrees )
{
float displacement = GetShortestAngularDisplacement( cu
entDegrees, goalDegrees );
if( displacement <= maxDeltaDegrees && displacement >= -maxDeltaDegrees )
return goalDegrees;
else if( displacement > maxDeltaDegrees )
return cu
entDegrees+maxDeltaDegrees;
else
return cu
entDegrees-maxDeltaDegrees;
}
every tick check and change Enemy status
void Enemy::Update( float deltaSeconds )
{
if( !IsAlive() )
return;
check if see enemy
Entity* visibleEnemy = m_theMap->RaycastForEnemyFaction( m_faction, m_position, ENEMY_DETECT_LENGTH );
if( visibleEnemy!=nullptr ){
can see enemy
m_goalPosReached = false;
m_goalAngleReached = true;
m_goalPos = visibleEnemy->m_position;
CheckToShoot(deltaSeconds);
}
else {
can't see enemy
check if see pickup
EntityFaction oppoFaction = m_faction == FACTION_GOOD ? FACTION_EVIL : FACTION_GOOD;
Entity* visiblePickup = m_theMap->RaycastForEnemyType( oppoFaction, ENTITY_TYPE_PICKUP, m_position, ENEMY_DETECT_LENGTH );
if( visiblePickup != nullptr ){
m_goalPosReached = false;
m_goalPosReached = true;
m_goalPos = visiblePickup->m_position;
}
}
move toward goal position
if( !m_goalPosReached ){
UpdateForGoalPosNotReached();
}
Revise orientation to avoid prolonged collision with solid tiles
if( m_goalAngleReached ){
UpdateWhiskerDetection();
}
no goal position, turn to randomized goal orientation
if(m_goalPosReached){
UpdateForGoalPosReached( deltaSeconds );
}
check if reach goal angle
if( m_goalOrientation == m_orientationDegrees ){
m_goalAngleReached = true;
}
set orientation
m_orientationDegrees = GetTurnedToward( m_orientationDegrees, m_goalOrientation, ENEMY_TURN_SPEED * deltaSeconds );
set velocity
float deltaDegreesToGoal = m_goalOrientation - m_orientationDegrees;
if( deltaDegreesToGoal > ENEMY_FORWARD_DEGREES || deltaDegreesToGoal < -ENEMY_FORWARD_DEGREES ){
m_velocity = .4f * m_speedLimit * Vec2::MakeFromPolarDegrees( m_orientationDegrees );
}
else{
m_velocity = m_speedLimit * Vec2::MakeFromPolarDegrees( m_orientationDegrees );
}
update
Entity::Update( deltaSeconds );
}
check if should shoot
void Enemy::CheckToShoot(float deltaSeconds)
{
float enemyToGoalDegrees = (m_goalPos - m_position).GetAngleDegrees();
float deltaDegreesToGoal = enemyToGoalDegrees - m_orientationDegrees;
if( deltaDegreesToGoal
-ENEMY_SHOOT_DEGREES ){
could shoot
if( m_shootCountdown <= 0.f ){
ShootBullet();
m_shootCountdown = ENEMY_SHOOT_COOLDOWN;
}
else{
cool down
m_shootCountdown -= deltaSeconds;
}
}
else{
m_shootCountdown = 0.f;
}
}
check if goal pos reached
void Enemy::UpdateForGoalPosNotReached()
{
Vec2 enemyToPlayer = (m_goalPos - m_position);
if( enemyToPlayer.GetLength() < m_physicsRadius ){
m_goalPosReached = true;
}
else{
m_goalOrientation = enemyToPlayer.GetAngleDegrees();
}
}
when goal position already reached
void Enemy::UpdateForGoalPosReached( float deltaSeconds )
{
if( m_resetGoalOrienCountdown <= 0.f ){
m_goalOrientation = g_theGame->m_RNG->RollRandomFloatInRange( 0.f, 360.f );
m_resetGoalOrienCountdown = ENEMY_TURN_COUNTDOWN;
}
else {
m_resetGoalOrienCountdown -= deltaSeconds;
}
}
Avoid constant collision with solid tiles
void Enemy::UpdateWhiskerDetection()
{
Vec2 forward = Vec2::MakeFromPolarDegrees( m_orientationDegrees );
Vec2 side = forward.GetRotated90Degrees();
m_leftWhiskerResult = m_theMap->Raycast( m_position + side * m_physicsRadius, forward, 1.f );
m_rightWhiskerResult = m_theMap->Raycast( m_position - side * m_physicsRadius, forward, 1.f );
m_centerWhiskerResult = m_theMap->Raycast( m_position, forward, 1.f );
if( m_leftWhiskerResult.m_impacted || m_rightWhiskerResult.m_impacted || m_centerWhiskerResult.m_impacted ) {
if( m_leftWhiskerResult.m_impacted && m_rightWhiskerResult.m_impacted && m_centerWhiskerResult.m_impacted ){
stuck in corne
m_goalOrientation = -m_orientationDegrees;
m_goalAngleReached = false;
}
else if( m_leftWhiskerResult.m_impacted && !m_rightWhiskerResult.m_impacted ) {
should turn right
m_goalOrientation = m_leftWhiskerResult.m_impactNormal.GetAngleDegrees() + 70.f;
}
else if( m_rightWhiskerResult.m_impacted && !m_leftWhiskerResult.m_impacted ) {
should turn left
m_goalOrientation = m_rightWhiskerResult.m_impactNormal.GetAngleDegrees() - 70.f;
}
else {
oth stuck
float m_leftWhiskerRevised = m_leftWhiskerResult.m_impactNormal.GetAngleDegrees() + 70.f;
float m_rightWhiskerRevised = m_rightWhiskerResult.m_impactNormal.GetAngleDegrees() - 70.f;
if( m_goalPosReached ){
if( m_leftWhiskerResult.m_impactDist < m_rightWhiskerResult.m_impactDist ){
m_goalOrientation = m_leftWhiskerRevised;
}
else{
m_goalOrientation = m_rightWhiskerRevised;
}
}
else{
float enemyToPlayerDegrees = (m_goalPos - m_position).GetAngleDegrees();
ight bette
if( IsAbsValueBigger( GetShortestAngularDisplacement(m_leftWhiskerRevised,enemyToPlayerDegrees),
GetShortestAngularDisplacement(m_rightWhiskerRevised, enemyToPlayerDegrees ) )) {
m_goalOrientation = m_rightWhiskerRevised;
}
else {
m_goalOrientation = m_leftWhiskerRevised;
...