add enemies and fix angles

This commit is contained in:
PoliEcho 2025-08-24 10:21:20 +02:00
parent 3f9d68252e
commit a1fa102c4a
11 changed files with 230 additions and 52 deletions

View File

@ -12,3 +12,4 @@ constexpr Uint64 TARGET_FRAME_TIME_NS = 1'000'000'000 / TARGET_FPS;
#define HEIGHT_RATIO 41.53846153846154
#define MIN_INPUT_DELAY_MOVEMENT 0
#define MIN_INPUT_DELAY_FIRE 200
#define NORMAL_PROJECTILE_SPEED 3

74
src/enemies.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "const.hpp"
#include "main.hpp"
#include "meth.hpp"
#include "misc.hpp"
#include "projectiles.hpp"
#include "types.hpp"
#include <SDL3/SDL_render.h>
#include <vector>
enemy_type spawn_enemy(enemy_ai_type ai_type, Uint32 reload_time) {
enemy_type enemy;
enemy.ship.texture = texture_from_SVG_file("assets/enemy_1.svg", 1);
enemy.type = ai_type;
enemy.reload_time = reload_time;
enemy.ship.rect = {
static_cast<float>(mode->w),
static_cast<float>(get_random_num(0, mode->h - enemy.ship.texture->h)),
static_cast<float>(enemy.ship.texture->w),
static_cast<float>(enemy.ship.texture->h)};
enemy.ship.gun_offset.x = 0;
enemy.ship.gun_offset.y = 0.5f * enemy.ship.texture->h;
enemy.size_multiplier = 1;
return enemy;
}
void step_enemy(enemy_type &e, ship_type &player,
std::vector<projectile> &projectiles) {
switch (e.type) {
case RANDOM:
switch (get_random_num(0, 3)) {
case 0:
e.ship.rect.x++;
break;
case 1:
e.ship.rect.x -= 2;
break;
case 2:
e.ship.rect.y++;
break;
case 3:
e.ship.rect.y--;
break;
}
if (get_random_num(0, 1000) == 0 &&
SDL_GetTicks() - e.last_shot > e.reload_time) {
projectiles.push_back(
spawn_projectile({e.ship.rect.x + e.ship.gun_offset.x,
e.ship.rect.y + e.ship.gun_offset.y},
e.size_multiplier, 270, NORMAL_PROJECTILE_SPEED,
"assets/basic_projectile.svg", nullptr));
}
break;
case FLYER:
if (e.ship.rect.x != e.target.x && e.ship.rect.y != e.target.y) {
if (e.ship.rect.y < mode->h / 2) {
e.target.y = 0;
} else {
e.target.y = mode->h - e.ship.rect.h;
}
e.target.x = e.ship.rect.x - (e.ship.rect.w / 2);
}
break;
case GUNNER:
break;
case ACE:
break;
case BOSS:
break;
}
SDL_RenderTexture(main_sdl_session.renderer, e.ship.texture, nullptr,
&e.ship.rect);
}

6
src/enemies.hpp Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "types.hpp"
#include <vector>
enemy_type spawn_enemy(enemy_ai_type ai_type, Uint32 reload_time);
void step_enemy(enemy_type &e, ship_type &player,
std::vector<projectile> &projectiles);

View File

@ -1,7 +1,10 @@
#include "const.hpp"
#include "enemies.hpp"
#include "main.hpp"
#include "meth.hpp"
#include "projectiles.hpp"
#include "types.hpp"
#include <climits>
#include <cstring>
#include <vector>
@ -37,7 +40,7 @@ bool play_level() {
Uint8 player_ship_speed = 1;
std::vector<projectile> projectiles;
std::vector<ship_type> enemies;
std::vector<enemy_type> enemies;
while (running) {
const Uint64 frameStart = SDL_GetTicksNS();
@ -97,14 +100,26 @@ bool play_level() {
projectiles.push_back(
spawn_projectile({player_ship.rect.x + player_ship.gun_offset.x,
player_ship.rect.y + player_ship.gun_offset.y},
1, 0, 3, "assets/basic_projectile.svg", nullptr));
1, 90, NORMAL_PROJECTILE_SPEED,
"assets/basic_projectile.svg", nullptr));
last_fire = SDL_GetTicks();
}
}
// chance to spawn enemy every frame
if (get_random_num(0, 10) == 0) {
enemies.push_back(spawn_enemy(
// static_cast<enemy_ai_type>(get_random_num(RANDOM, GUNNER)),
RANDOM, get_random_num(200, 1000)));
}
SDL_SetRenderDrawColor(main_sdl_session.renderer, 0, 0, 0, 255);
SDL_RenderClear(main_sdl_session.renderer);
for (enemy_type &e : enemies) {
step_enemy(e, player_ship, projectiles);
}
for (projectile &p : projectiles) {
if (p.rect.x > mode->w || p.rect.y > mode->h) {
projectiles.erase(projectiles.begin() + (&p - projectiles.data()));
@ -133,4 +148,5 @@ bool play_level() {
}
SDL_DestroyTexture(player_ship.texture);
return true;
}

View File

@ -1,4 +1,5 @@
#include "game_logic.hpp"
#include "meth.hpp"
#include "types.hpp"
#include <SDL3/SDL.h>
#include <SDL3/SDL_events.h>
@ -11,6 +12,7 @@
#include <SDL3/SDL_timer.h>
#include <SDL3/SDL_video.h>
#include <SDL3_image/SDL_image.h>
#include <iomanip>
sdl_session main_sdl_session;
const SDL_DisplayMode *mode;

View File

@ -1,27 +1,25 @@
#include "types.hpp"
#include <cmath>
#include <random>
SDL_FPoint find_dst_point_with_angle_and_distance(SDL_FPoint start, Angle angle,
float distance) {
float angle_rad = (angle - 90) * M_PI / 180.0f;
float angle_degrees = static_cast<float>(angle);
float angle_rad = (angle_degrees - 90.0f) * M_PI / 180.0f;
float dx = std::cos(angle_rad) * distance;
float dy = std::sin(angle_rad) * distance;
float calculated_distance = std::sqrt(dx * dx + dy * dy);
SDL_FPoint result;
if (calculated_distance > 0) {
dx /= calculated_distance;
dy /= calculated_distance;
result.x = start.x + dx * distance;
result.y = start.y + dy * distance;
} else {
result.x = start.x;
result.y = start.y;
}
result.x = start.x + dx;
result.y = start.y + dy;
return result;
}
int get_random_num(int min, int max) {
static std::random_device dev;
static std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist(min, max);
return dist(rng);
}

View File

@ -2,4 +2,5 @@
#include "types.hpp"
#include <SDL3/SDL_rect.h>
SDL_FPoint find_dst_point_with_angle_and_distance(SDL_FPoint start, Angle angle,
float distance);
float distance);
int get_random_num(int min, int max);

26
src/misc.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "main.hpp"
#include <SDL3/SDL_render.h>
#include <SDL3_image/SDL_image.h>
#include <array>
SDL_Texture *texture_from_SVG_file(const char *file_name,
float size_multiplier) {
SDL_IOStream *texture_file = SDL_IOFromFile(file_name, "r");
std::array<int, 2> texture_base_size;
{
SDL_Surface *tmp_surface = IMG_LoadSVG_IO(texture_file);
texture_base_size = {tmp_surface->w, tmp_surface->h};
SDL_DestroySurface(tmp_surface);
}
SDL_SeekIO(texture_file, 0, SDL_IO_SEEK_SET); // reset to top of the file
SDL_Surface *projectile_surface =
IMG_LoadSizedSVG_IO(texture_file, texture_base_size[0] * size_multiplier,
texture_base_size[1] * size_multiplier);
SDL_CloseIO(texture_file);
SDL_Texture *texture = SDL_CreateTextureFromSurface(main_sdl_session.renderer,
projectile_surface);
SDL_DestroySurface(projectile_surface);
return texture;
}

4
src/misc.hpp Normal file
View File

@ -0,0 +1,4 @@
#include <SDL3/SDL_render.h>
#include <SDL3/SDL_stdinc.h>
SDL_Texture *texture_from_SVG_file(const char *file_name,
float size_multiplier);

View File

@ -1,6 +1,7 @@
#include "macro.hpp"
#include "main.hpp"
#include "meth.hpp"
#include "misc.hpp"
#include "types.hpp"
#include <SDL3/SDL.h>
#include <SDL3/SDL_rect.h>
@ -15,23 +16,8 @@ projectile spawn_projectile(SDL_FPoint position, float size_multiplier,
SDL_FRect *target) {
projectile p;
SDL_IOStream *texture_file = SDL_IOFromFile(texture_file_name, "r");
std::array<int, 2> texture_base_size;
{
SDL_Surface *tmp_surface = IMG_LoadSVG_IO(texture_file);
texture_base_size = {tmp_surface->w, tmp_surface->h};
SDL_DestroySurface(tmp_surface);
}
SDL_SeekIO(texture_file, 0, SDL_IO_SEEK_SET); // reset to top of the file
SDL_Surface *projectile_surface =
IMG_LoadSizedSVG_IO(texture_file, texture_base_size[0] * size_multiplier,
texture_base_size[1] * size_multiplier);
SDL_CloseIO(texture_file);
p.texture = SDL_CreateTextureFromSurface(main_sdl_session.renderer,
projectile_surface);
SDL_DestroySurface(projectile_surface);
p.texture =
texture_from_SVG_file("assets/basic_projectile.svg", size_multiplier);
p.angle = angle;
p.rect = {position.x, position.y, static_cast<float>(p.texture->w),

View File

@ -16,7 +16,6 @@ enum enemy_ai_type {
struct Angle {
private:
float value{0};
void normalize() {
value = std::fmod(value, 360);
if (value < 0)
@ -24,77 +23,140 @@ private:
}
public:
// Constructor
Angle(int val = 0) : value(val) { normalize(); }
// Constructors
Angle(int val = 0) : value(static_cast<float>(val)) { normalize(); }
Angle(float val) : value(val) { normalize(); }
Angle(double val) : value(static_cast<float>(val)) { normalize(); }
// Assignment operator
// Assignment operators
Angle &operator=(int val) {
value = static_cast<float>(val);
normalize();
return *this;
}
Angle &operator=(float val) {
value = val;
normalize();
return *this;
}
Angle &operator=(double val) {
value = static_cast<float>(val);
normalize();
return *this;
}
// Compound assignment
Angle &operator+=(int rhs) {
value += rhs;
value += static_cast<float>(rhs);
normalize();
return *this;
}
Angle &operator-=(int rhs) {
value -= static_cast<float>(rhs);
normalize();
return *this;
}
Angle &operator+=(float rhs) {
value += rhs;
normalize();
return *this;
}
Angle &operator-=(float rhs) {
value -= rhs;
normalize();
return *this;
}
// Binary operators for int
Angle operator+(int rhs) const {
return Angle(static_cast<int>(value) + rhs);
Angle result;
result.value = value + static_cast<float>(rhs);
result.normalize();
return result;
}
Angle operator-(int rhs) const {
return Angle(static_cast<int>(value) - rhs);
Angle result;
result.value = value - static_cast<float>(rhs);
result.normalize();
return result;
}
Angle operator*(int rhs) const {
return Angle(static_cast<int>(value * rhs));
Angle result;
result.value = value * static_cast<float>(rhs);
result.normalize();
return result;
}
Angle operator/(int rhs) const {
return Angle(static_cast<int>(value / rhs));
Angle result;
result.value = value / static_cast<float>(rhs);
result.normalize();
return result;
}
// Binary operators for double
Angle operator+(double rhs) const {
return Angle(static_cast<int>(value + rhs));
Angle result;
result.value = value + static_cast<float>(rhs);
result.normalize();
return result;
}
Angle operator-(double rhs) const {
return Angle(static_cast<int>(value - rhs));
Angle result;
result.value = value - static_cast<float>(rhs);
result.normalize();
return result;
}
Angle operator*(double rhs) const {
return Angle(static_cast<int>(value * rhs));
Angle result;
result.value = value * static_cast<float>(rhs);
result.normalize();
return result;
}
Angle operator/(double rhs) const {
return Angle(static_cast<int>(value / rhs));
Angle result;
result.value = value / static_cast<float>(rhs);
result.normalize();
return result;
}
// Binary operators for float
Angle operator+(float rhs) const {
return Angle(static_cast<int>(value + rhs));
Angle result;
result.value = value + rhs;
result.normalize();
return result;
}
Angle operator-(float rhs) const {
return Angle(static_cast<int>(value - rhs));
Angle result;
result.value = value - rhs;
result.normalize();
return result;
}
Angle operator*(float rhs) const {
return Angle(static_cast<int>(value * rhs));
Angle result;
result.value = value * rhs;
result.normalize();
return result;
}
Angle operator/(float rhs) const {
return Angle(static_cast<int>(value / rhs));
Angle result;
result.value = value / rhs;
result.normalize();
return result;
}
// Type conversion
@ -124,6 +186,8 @@ struct enemy_type {
enemy_ai_type type;
Uint32 last_shot;
Uint32 reload_time;
SDL_FPoint target;
float size_multiplier;
};
struct projectile {