645 lines
22 KiB
C
645 lines
22 KiB
C
#ifndef KKND_H
|
|
#define KKND_H
|
|
|
|
/* =========================================================================
|
|
* openkknd - Krush, Kill 'n' Destroy style 2D Real-Time Strategy engine
|
|
* Single merged codebase (was: openkknd + openkknd_full).
|
|
*
|
|
* This header declares the complete shared type system and the public
|
|
* interface of every engine subsystem. The implementation lives in the
|
|
* matching src/*.c translation units.
|
|
* ========================================================================= */
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
#include <SDL2/SDL.h>
|
|
#include <SDL2/SDL_ttf.h>
|
|
/* SDL_image is optional; engine uses procedural sprites + custom PNG writer. */
|
|
#if defined(KKND_HAVE_SDL_IMAGE) && KKND_HAVE_SDL_IMAGE
|
|
#include <SDL2/SDL_image.h>
|
|
#endif
|
|
|
|
#include "unit_card.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Global tunables */
|
|
/* ----------------------------------------------------------------------- */
|
|
#define KKND_NAME "openkknd"
|
|
#define KKND_VERSION "1.0.0"
|
|
|
|
#define TILE 32 /* pixel size of one map tile */
|
|
#define MAP_W 128 /* map width in tiles */
|
|
#define MAP_H 128 /* map height in tiles */
|
|
#define MAP_PIX_W (MAP_W * TILE)
|
|
#define MAP_PIX_H (MAP_H * TILE)
|
|
|
|
#define MAX_UNITS 3000
|
|
#define MAX_BUILDINGS 1024
|
|
#define MAX_BULLETS 6000
|
|
#define MAX_PARTICLES 4000
|
|
#define MAX_PATH 1024
|
|
#define MAX_SELECTION 256
|
|
#define MAX_FACTIONS 4
|
|
|
|
#define VIEW_W 1280
|
|
#define VIEW_H 720
|
|
|
|
#define START_SCRAP 1500 /* starting resource for each side */
|
|
#define SCRAP_PER_TILE 1000 /* scrap contained in one scrap field */
|
|
|
|
#define SAVE_MAGIC 0x4B4B4E44 /* 'KKND' */
|
|
#define SAVE_VERSION 2
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Enumerations */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef enum {
|
|
T_WASTELAND = 0,
|
|
T_RUBBLE,
|
|
T_ROAD,
|
|
T_GRASS,
|
|
T_WATER,
|
|
T_ROCK,
|
|
T_SCRAP,
|
|
T_COUNT
|
|
} TerrainType;
|
|
|
|
typedef enum {
|
|
FACTION_NONE = 0,
|
|
FACTION_SURVIVOR, /* player - post-war military remnants */
|
|
FACTION_EVOLVED, /* ai - mutated wasteland beasties */
|
|
FACTION_SERIES9, /* neutral - rogue war machines */
|
|
FACTION_NEUTRAL
|
|
} Faction;
|
|
|
|
typedef enum {
|
|
UT_NONE = 0,
|
|
UT_INFANTRY,
|
|
UT_BUGGY,
|
|
UT_TANK,
|
|
UT_HARVESTER,
|
|
UT_ARTILLERY,
|
|
UT_JEEP,
|
|
UT_MUTANT,
|
|
UT_BEAST,
|
|
UT_RAVAGER,
|
|
UT_FLAME,
|
|
UT_MISSILE,
|
|
UT_MEDIC,
|
|
UT_COUNT
|
|
} UnitType;
|
|
|
|
typedef enum {
|
|
AB_NONE = 0,
|
|
AB_SIEGE, /* tanks/artillery: +range, immobile while active */
|
|
AB_HEAL /* medics: pulse heal nearby allies */
|
|
} AbilityType;
|
|
|
|
typedef enum {
|
|
BT_NONE = 0,
|
|
BT_BASE, /* command centre / HQ */
|
|
BT_WARFACTORY,
|
|
BT_REFINERY,
|
|
BT_POWER,
|
|
BT_TURRET,
|
|
BT_WALL,
|
|
BT_REPAIR,
|
|
BT_RESEARCH,
|
|
BT_COUNT
|
|
} BuildingType;
|
|
|
|
typedef enum {
|
|
STATE_IDLE = 0,
|
|
STATE_MOVING,
|
|
STATE_ATTACKING,
|
|
STATE_GATHERING,
|
|
STATE_RETURNING,
|
|
STATE_DEAD
|
|
} UnitState;
|
|
|
|
typedef enum {
|
|
ORDER_NONE = 0,
|
|
ORDER_MOVE,
|
|
ORDER_ATTACKMOVE,
|
|
ORDER_ATTACK,
|
|
ORDER_GATHER,
|
|
ORDER_RETURN,
|
|
ORDER_BUILD,
|
|
ORDER_STOP
|
|
} OrderType;
|
|
|
|
typedef enum {
|
|
GAME_MENU = 0,
|
|
GAME_PLAYING,
|
|
GAME_PAUSED,
|
|
GAME_WON,
|
|
GAME_LOST
|
|
} GameState;
|
|
|
|
typedef enum {
|
|
DIFF_EASY = 0,
|
|
DIFF_NORMAL,
|
|
DIFF_HARD,
|
|
DIFF_COUNT
|
|
} Difficulty;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Small math helpers */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct { float x, y; } Vec2;
|
|
|
|
static inline float kknd_dist2(float ax, float ay, float bx, float by) {
|
|
float dx = ax - bx, dy = ay - by;
|
|
return dx * dx + dy * dy;
|
|
}
|
|
static inline float kknd_dist(float ax, float ay, float bx, float by) {
|
|
return (float)sqrtf(kknd_dist2(ax, ay, bx, by));
|
|
}
|
|
static inline float kknd_clampf(float v, float lo, float hi) {
|
|
return v < lo ? lo : (v > hi ? hi : v);
|
|
}
|
|
static inline int kknd_clampi(int v, int lo, int hi) {
|
|
return v < lo ? lo : (v > hi ? hi : v);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Deterministic RNG (xoroshiro128**) */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
uint64_t s[2];
|
|
} RNG;
|
|
|
|
void rng_seed(RNG *r, uint64_t seed);
|
|
uint64_t rng_u64(RNG *r);
|
|
uint32_t rng_u32(RNG *r);
|
|
int rng_range(RNG *r, int lo, int hi);
|
|
float rng_f32(RNG *r);
|
|
float rng_frange(RNG *r, float lo, float hi);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Map */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
uint8_t terrain; /* TerrainType */
|
|
uint8_t walkable; /* 0 = blocked, 1 = passable */
|
|
uint8_t scrap; /* remaining scrap (0..255) */
|
|
uint8_t variant; /* cosmetic variation */
|
|
uint8_t occupied; /* building footprint marker */
|
|
} Tile;
|
|
|
|
typedef struct {
|
|
int w, h;
|
|
Tile *tiles; /* w*h */
|
|
uint8_t *fog; /* human visibility: 0 hidden,1 explored,2 visible */
|
|
int scrap_fields; /* number of scrap deposits */
|
|
int style; /* terrain theme */
|
|
int spawn_x[MAX_FACTIONS];
|
|
int spawn_y[MAX_FACTIONS];
|
|
} GameMap;
|
|
|
|
void map_init(GameMap *m, RNG *rng);
|
|
void map_free(GameMap *m);
|
|
Tile *map_tile(GameMap *m, int tx, int ty);
|
|
int map_walkable(GameMap *m, int tx, int ty);
|
|
int map_in_bounds(GameMap *m, int tx, int ty);
|
|
void map_world_to_tile(float wx, float wy, int *tx, int *ty);
|
|
void map_tile_to_world(int tx, int ty, float *wx, float *wy);
|
|
int map_find_nearest_scrap(GameMap *m, float wx, float wy, float *outx, float *outy);
|
|
void map_deplete_scrap(GameMap *m, int tx, int ty, int amount);
|
|
typedef struct Game Game;
|
|
void map_update_fog(Game *g, Faction f);
|
|
|
|
/* A* pathfinding ------------------------------------------------------- */
|
|
typedef struct {
|
|
int tx, ty; /* tile coordinate */
|
|
} PathNode;
|
|
|
|
typedef struct {
|
|
PathNode nodes[MAX_PATH];
|
|
int len;
|
|
} Path;
|
|
|
|
int path_find(GameMap *m, int sx, int sy, int gx, int gy, Path *out);
|
|
void path_smooth(GameMap *m, Path *p);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Units */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct Unit {
|
|
int id;
|
|
UnitType type;
|
|
Faction faction;
|
|
float x, y; /* world position (pixels) */
|
|
float hp;
|
|
float max_hp;
|
|
float attack;
|
|
float defense;
|
|
float speed; /* pixels / second */
|
|
float range; /* pixels */
|
|
float sight; /* pixels */
|
|
float heading; /* radians, for sprite rotation */
|
|
UnitState state;
|
|
OrderType order;
|
|
int target_unit; /* id, -1 = none */
|
|
int target_bld; /* id, -1 = none */
|
|
float dest_x, dest_y;
|
|
Path path;
|
|
int path_idx;
|
|
float atk_cd; /* attack cooldown timer */
|
|
float cargo; /* harvester load */
|
|
int selected;
|
|
int dead;
|
|
float anim; /* walk/attack animation phase */
|
|
float repath_timer; /* throttle re-pathing */
|
|
int hold; /* hold position (don't chase) */
|
|
int attack_move; /* move toward dest but engage en route */
|
|
AbilityType ability; /* special ability, 0 = none */
|
|
float ability_cd; /* cooldown remaining */
|
|
int ability_on; /* active toggle (siege) */
|
|
float reload_mul; /* reload speed multiplier (upgrades) */
|
|
} Unit;
|
|
|
|
#define MAX_WRECKS 1024
|
|
typedef struct {
|
|
float x, y;
|
|
UnitType type;
|
|
Faction faction;
|
|
float rot;
|
|
} Wreck;
|
|
|
|
#define MAX_PARTICLES 2048
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Buildings */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct Building {
|
|
int id;
|
|
BuildingType type;
|
|
Faction faction;
|
|
int tx, ty; /* top-left tile */
|
|
int w, h; /* footprint in tiles */
|
|
float hp;
|
|
float max_hp;
|
|
float build; /* 0..1 construction progress */
|
|
int producing; /* UnitType being built, 0 = none */
|
|
float prod_timer;
|
|
float prod_total;
|
|
int queue[MAX_SELECTION];
|
|
int queue_len;
|
|
float rally_x, rally_y;
|
|
int selected;
|
|
int dead;
|
|
float atk_cd;
|
|
} Building;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Projectiles & particles */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
float x, y, tx, ty;
|
|
float speed;
|
|
float damage;
|
|
Faction faction;
|
|
int target_unit;
|
|
int target_bld;
|
|
float life;
|
|
int kind; /* 0 bullet, 1 shell, 2 laser, 3 missile */
|
|
} Bullet;
|
|
|
|
typedef struct {
|
|
float x, y;
|
|
float vx, vy;
|
|
float life;
|
|
float max_life;
|
|
uint8_t r, g, b;
|
|
int kind; /* 0 smoke, 1 fire, 2 spark, 3 debris */
|
|
} Particle;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Camera */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
float x, y; /* world top-left of view */
|
|
float zoom;
|
|
int shake;
|
|
} Camera;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Sprite cache */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
SDL_Texture *unit[UT_COUNT][MAX_FACTIONS];
|
|
SDL_Texture *bld[BT_COUNT][MAX_FACTIONS];
|
|
SDL_Texture *terrain[T_COUNT];
|
|
SDL_Texture *bullet[4];
|
|
TTF_Font *font_small;
|
|
TTF_Font *font_med;
|
|
TTF_Font *font_big;
|
|
} Sprites;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Research / upgrades (declared early so Game can embed it) */
|
|
/* ----------------------------------------------------------------------- */
|
|
#define UP_DAMAGE 0
|
|
#define UP_ARMOR 1
|
|
#define UP_SPEED 2
|
|
#define UP_RELOAD 3
|
|
#define UP_BUILD 4
|
|
#define UP_COUNT 5
|
|
#define UP_MAX_LVL 3
|
|
|
|
typedef struct { int lvl[UP_COUNT]; } Upgrades;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Game state */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct Game {
|
|
GameMap map;
|
|
Unit units[MAX_UNITS];
|
|
int unit_count;
|
|
int unit_next_id;
|
|
Building buildings[MAX_BUILDINGS];
|
|
int bld_count;
|
|
int bld_next_id;
|
|
Bullet bullets[MAX_BULLETS];
|
|
int bullet_count;
|
|
Particle particles[MAX_PARTICLES];
|
|
int particle_count;
|
|
|
|
int scrap[MAX_FACTIONS];
|
|
int power[MAX_FACTIONS];
|
|
int pop[MAX_FACTIONS];
|
|
int pop_cap[MAX_FACTIONS];
|
|
|
|
int selection[MAX_SELECTION];
|
|
int sel_count;
|
|
|
|
/* control groups (Ctrl+1..9 sets, 1..9 recalls) */
|
|
int groups[9][MAX_SELECTION];
|
|
int group_len[9];
|
|
|
|
Camera cam;
|
|
Sprites spr;
|
|
SDL_Renderer *ren;
|
|
SDL_Window *win;
|
|
|
|
GameState state;
|
|
Difficulty diff;
|
|
Faction human;
|
|
float time;
|
|
float speed_mul;
|
|
int winner;
|
|
int pause;
|
|
|
|
/* drag-selection rectangle (screen space) */
|
|
int drag_x0, drag_y0, drag_x1, drag_y1, dragging;
|
|
|
|
/* build placement ghost */
|
|
BuildingType place_type;
|
|
int placing;
|
|
|
|
float ai_timer;
|
|
float ai_wave[MAX_FACTIONS];
|
|
int frames;
|
|
|
|
/* on-screen message log (ring buffer) */
|
|
char log_msg[32][96];
|
|
int log_count;
|
|
int log_next;
|
|
|
|
/* research / upgrades */
|
|
Upgrades upg[MAX_FACTIONS];
|
|
int research_lab[MAX_FACTIONS];
|
|
int research_cur[MAX_FACTIONS];
|
|
float research_prog[MAX_FACTIONS];
|
|
|
|
/* mission */
|
|
int mission_id;
|
|
int objective;
|
|
Faction enemy; /* actual enemy for the active match */
|
|
int unlocked; /* highest unlocked mission id + 1 */
|
|
int menu_sel; /* highlighted mission in the menu */
|
|
float obj_timer;
|
|
|
|
/* wreckage decals */
|
|
Wreck *wrecks;
|
|
int wreck_count;
|
|
int wreck_next;
|
|
} Game;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Configuration / unit stats */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
const char *name;
|
|
UnitType type;
|
|
Faction faction;
|
|
int cost;
|
|
float hp;
|
|
float attack;
|
|
float defense;
|
|
float speed;
|
|
float range;
|
|
float sight;
|
|
int cargo;
|
|
int build_time; /* seconds to produce */
|
|
AbilityType ability; /* special ability, 0 = none */
|
|
const char *desc;
|
|
} UnitDef;
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
BuildingType type;
|
|
int cost;
|
|
int build_time;
|
|
float hp;
|
|
int w, h;
|
|
int provides_power;
|
|
int pop_provided;
|
|
int produces[UT_COUNT > 8 ? UT_COUNT : 8];
|
|
int produces_count;
|
|
int is_turret;
|
|
float atk;
|
|
float range;
|
|
int is_research; /* research lab flag */
|
|
const char *desc;
|
|
} BldDef;
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Missions / campaign */
|
|
/* ----------------------------------------------------------------------- */
|
|
#define OBJ_DESTROY_ALL 0
|
|
#define OBJ_SURVIVE 1
|
|
#define OBJ_GATHER 2
|
|
|
|
typedef struct {
|
|
int id;
|
|
const char *name;
|
|
const char *brief;
|
|
int objective;
|
|
Faction enemy;
|
|
int diff;
|
|
int scrap_goal; /* for OBJ_GATHER */
|
|
float survive_time; /* for OBJ_SURVIVE */
|
|
int map_style; /* terrain theme */
|
|
uint32_t seed;
|
|
} Mission;
|
|
|
|
/* Build the unit-card registries (merged feature) and stat tables. */
|
|
void config_init(void);
|
|
const UnitDef *unit_def(UnitType t, Faction f);
|
|
const BldDef *bld_def(BuildingType t);
|
|
UnitRegistry *unit_card_registry(void); /* for save/inspect */
|
|
UnitRegistry *bld_card_registry(void);
|
|
int mission_count(void);
|
|
const Mission *mission_get(int id);
|
|
const char *research_name(int up);
|
|
int research_cost(int up, int level);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Sprites */
|
|
/* ----------------------------------------------------------------------- */
|
|
int sprites_init(Sprites *s, SDL_Renderer *r);
|
|
void sprites_free(Sprites *s);
|
|
SDL_Texture *sprites_make_unit(SDL_Renderer *r, UnitType t, Faction f);
|
|
SDL_Texture *sprites_make_bld(SDL_Renderer *r, BuildingType t, Faction f);
|
|
SDL_Texture *sprites_make_terrain(SDL_Renderer *r, TerrainType t);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Units */
|
|
/* ----------------------------------------------------------------------- */
|
|
int unit_spawn(Game *g, UnitType t, Faction f, float x, float y);
|
|
void unit_remove(Game *g, int idx);
|
|
void unit_update(Game *g, float dt);
|
|
void unit_issue_move(Game *g, int idx, float x, float y, int attackmove);
|
|
void unit_issue_move_group(Game *g, const int *idxs, int n, float cx, float cy, int attackmove);
|
|
void unit_issue_attack_unit(Game *g, int idx, int target);
|
|
void unit_issue_attack_bld(Game *g, int idx, int target);
|
|
void unit_issue_gather(Game *g, int idx, float x, float y);
|
|
void unit_issue_gather_nearest(Game *g, int idx);
|
|
void unit_issue_return(Game *g, int idx);
|
|
void unit_issue_stop(Game *g, int idx);
|
|
void unit_issue_hold(Game *g, int idx);
|
|
void unit_ability_use(Game *g, int idx);
|
|
void unit_apply_damage(Game *g, Unit *u, float dmg);
|
|
Unit *unit_by_id(Game *g, int id);
|
|
void unit_select_in_rect(Game *g, int x0, int y0, int x1, int y1, int add);
|
|
void unit_select_single(Game *g, int idx, int add);
|
|
void unit_clear_selection(Game *g);
|
|
void unit_select_all(Game *g, Faction f);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Buildings */
|
|
/* ----------------------------------------------------------------------- */
|
|
int bld_spawn(Game *g, BuildingType t, Faction f, int tx, int ty);
|
|
void bld_remove(Game *g, int idx);
|
|
void bld_update(Game *g, float dt);
|
|
void bld_queue_unit(Game *g, int idx, UnitType t);
|
|
Building *bld_by_id(Game *g, int id);
|
|
int bld_can_place(Game *g, BuildingType t, int tx, int ty);
|
|
void bld_apply_damage(Game *g, Building *b, float dmg);
|
|
int bld_research(Game *g, Faction f, int up);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Projectiles & particles */
|
|
/* ----------------------------------------------------------------------- */
|
|
void bullet_spawn(Game *g, float x, float y, int target_unit, int target_bld,
|
|
float dmg, Faction f, int kind);
|
|
void bullet_update(Game *g, float dt);
|
|
void particle_spawn(Game *g, float x, float y, int kind, uint8_t cr, uint8_t cg, uint8_t cb);
|
|
void particle_burst(Game *g, float x, float y, int n, int kind, uint8_t cr, uint8_t cg, uint8_t cb);
|
|
void particle_update(Game *g, float dt);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Rendering */
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef struct {
|
|
int x, y, w, h;
|
|
int kind; /* 0 = structure button, 1 = unit button */
|
|
int id; /* BuildingType or UnitType */
|
|
const char *label;
|
|
int enabled;
|
|
int cost;
|
|
} HudButton;
|
|
|
|
int render_init(Game *g);
|
|
void render_frame(Game *g);
|
|
void render_world(Game *g);
|
|
void render_units(Game *g);
|
|
void render_buildings(Game *g);
|
|
void render_bullets(Game *g);
|
|
void render_particles(Game *g);
|
|
void render_selection(Game *g);
|
|
void render_hud(Game *g);
|
|
void render_minimap(Game *g);
|
|
void render_text(Sprites *s, SDL_Renderer *r, TTF_Font *f,
|
|
const char *txt, int x, int y, SDL_Color c);
|
|
void render_build_menu(Game *g);
|
|
void hud_layout(Game *g, HudButton *out, int *n);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Input */
|
|
/* ----------------------------------------------------------------------- */
|
|
void input_handle(Game *g, SDL_Event *e);
|
|
void input_camera(Game *g, float dt);
|
|
int input_screen_to_world(Game *g, int sx, int sy, float *wx, float *wy);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* AI */
|
|
/* ----------------------------------------------------------------------- */
|
|
void ai_update(Game *g, float dt);
|
|
void ai_command(Faction f, int diff);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Audio */
|
|
/* ----------------------------------------------------------------------- */
|
|
int audio_init(void);
|
|
void audio_shutdown(void);
|
|
void audio_sfx(int id); /* 0 move,1 shoot,2 explode,3 build,4 select,5 error */
|
|
void audio_music_start(void);
|
|
void audio_music_stop(void);
|
|
void audio_music_tick(float dt);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Save / load */
|
|
/* ----------------------------------------------------------------------- */
|
|
int save_game(Game *g, const char *path);
|
|
int load_game(Game *g, const char *path);
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/* Engine */
|
|
/* ----------------------------------------------------------------------- */
|
|
extern int g_headless; /* when 1, run simulation without any renderer */
|
|
extern int g_auto; /* when 1, the human faction is also AI-driven */
|
|
void engine_init(Game *g, const char *title);
|
|
void engine_shutdown(Game *g);
|
|
|
|
void engine_setup_match(Game *g, int mission_id);
|
|
void engine_update(Game *g, float dt);
|
|
void engine_check_win(Game *g);
|
|
void engine_log(const char *fmt, ...);
|
|
void game_log(Game *g, const char *fmt, ...);
|
|
|
|
/* Helpers */
|
|
int png_save(const char *path, int w, int h, const uint8_t *rgba);
|
|
void snapshot_capture(Game *g, const char *path);
|
|
Faction enemy_of(Faction f);
|
|
const char *faction_name(Faction f);
|
|
const char *unit_name(UnitType t, Faction f);
|
|
SDL_Color faction_color(Faction f);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* KKND_H */
|