add enemies and fix angles
This commit is contained in:
parent
3f9d68252e
commit
a1fa102c4a
@ -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
74
src/enemies.cpp
Normal 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
6
src/enemies.hpp
Normal 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);
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
28
src/meth.cpp
28
src/meth.cpp
@ -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);
|
||||
}
|
||||
|
@ -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
26
src/misc.cpp
Normal 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
4
src/misc.hpp
Normal 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);
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user