first half of smart missiles

This commit is contained in:
KikooDX 2021-12-21 00:14:49 +01:00
parent e912ed7b9a
commit 72ad64c780
14 changed files with 175 additions and 3 deletions

View File

@ -11,6 +11,7 @@ include_directories(inc)
set(SOURCES
src/main.c
src/vec.c
src/util.c
src/draw.c
src/input.c
@ -19,6 +20,7 @@ set(SOURCES
src/player.c
src/polarity.c
src/time.c
src/missile.c
)
set(ASSETS

View File

@ -22,3 +22,6 @@
#define BOUNCE_SPEED -2.0f
#define DRAW_OFF_X -2
#define GRAVS_MARGIN 0
#define MISSILE_MAX_SPEED 4.0f
#define MISSILE_ACCEL 0.06f
#define MISSILE_FRICTION (MISSILE_ACCEL / MISSILE_MAX_SPEED)

View File

@ -12,6 +12,7 @@ enum Key {
K_EDITOR,
K_SCROLL_UP,
K_SCROLL_DOWN,
K_DEBUG,
K_COUNT
};
enum KeyState { KS_UP, KS_DOWN, KS_PRESS };

View File

@ -39,4 +39,5 @@ int level_get_px(int x, int y);
void level_set(int x, int y, int v);
void level_set_px(int x, int y, int v);
struct Vec level_find(enum Tile);
int level_count(enum Tile);
struct Vec level_dim(void);

18
inc/missile.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "vec.h"
struct Missile {
int active;
struct VecF pos, spd;
};
struct MissileManager {
int n_missiles;
struct Missile *missiles;
};
void missile_manager_init(void);
void missile_manager_free(void);
void missile_manager_update(struct VecF target);
void missile_manager_draw(void);
struct Missile *missile_new(int x, int y);

View File

@ -12,5 +12,7 @@ struct Player {
void player_spawn(struct Player *);
void player_update(struct Player *);
void player_draw(struct Player *);
void player_draw(const struct Player *);
void player_move(struct Player *, struct Vec);
struct Vec player_middle(const struct Player *);

View File

@ -16,6 +16,7 @@ enum Tile {
TILE_WATER,
TILE_BURN_RED,
TILE_BURN_BLUE,
TILE_MISSILE_LAUNCHER,
TILE_COUNT,
TILE_OOB = TILE_BURN,
};

View File

@ -7,3 +7,8 @@ struct Vec {
struct VecF {
float x, y;
};
struct VecF vecf(struct Vec);
struct Vec vec(struct VecF);
struct VecF normalize(struct VecF);

View File

@ -4,7 +4,7 @@
static struct Input input;
static const int default_map[K_COUNT] = {
KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_SHIFT, KEY_ALPHA,
KEY_EXIT, KEY_TAN, KEY_F3, KEY_F2, KEY_F1};
KEY_EXIT, KEY_TAN, KEY_F3, KEY_F2, KEY_F1, KEY_F6};
void
input_init(void)

View File

@ -1,5 +1,6 @@
#include "level.h"
#include "conf.h"
#include "missile.h"
#include "player.h"
#include "polarity.h"
#include "tile.h"
@ -62,6 +63,7 @@ level_load(int id)
polarity_reset();
level_regen_visual_data(0);
player_spawn(level.player);
missile_manager_init();
}
void
@ -169,6 +171,16 @@ level_find(enum Tile t)
return (struct Vec){i % level.width, i / level.width};
}
int
level_count(enum Tile t)
{
int c = 0;
int i = level.size;
while (i-- > 0)
c += level.data[i] == t;
return c;
}
struct Vec
level_dim(void)
{

View File

@ -2,6 +2,7 @@
#include "editor.h"
#include "input.h"
#include "level.h"
#include "missile.h"
#include "player.h"
#include "time.h"
#include "util.h"
@ -70,6 +71,7 @@ static void
deinit(void)
{
level_deinit();
missile_manager_free();
timer_stop(timer);
}
@ -78,9 +80,12 @@ static void
update(void)
{
input_update();
missile_manager_update(vecf(player_middle(&player)));
player_update(&player);
/* enter editor */
if (input_pressed(K_EDITOR)) editor();
/* debug: spawn missile */
if (input_pressed(K_DEBUG)) missile_new(DWIDTH / 2, DHEIGHT / 2);
}
static void
@ -88,6 +93,7 @@ draw(void)
{
dclear(C_BLACK);
level_draw();
missile_manager_draw();
player_draw(&player);
level_draw_name();
time_draw();

91
src/missile.c Normal file
View File

@ -0,0 +1,91 @@
#include "missile.h"
#include "conf.h"
#include "level.h"
#include <gint/display.h>
#include <stdlib.h>
static struct MissileManager manager = {.missiles = NULL};
static void missile_update(struct Missile *, struct VecF target);
static void missile_draw(const struct Missile *);
void
missile_manager_init(void)
{
int i;
missile_manager_free();
/* debug: remove the `1 + ` later on */
manager.n_missiles = 1 + level_count(TILE_MISSILE_LAUNCHER);
manager.missiles = malloc(manager.n_missiles * sizeof(struct Missile));
i = manager.n_missiles;
while (i-- > 0)
manager.missiles[i].active = 0;
}
void
missile_manager_free(void)
{
if (manager.missiles != NULL) free(manager.missiles);
}
void
missile_manager_update(struct VecF target)
{
int i = manager.n_missiles;
while (i-- > 0)
if (manager.missiles[i].active)
missile_update(&manager.missiles[i], target);
}
void
missile_manager_draw(void)
{
int i = manager.n_missiles;
while (i-- > 0)
if (manager.missiles[i].active)
missile_draw(&manager.missiles[i]);
}
struct Missile *
missile_new(int x, int y)
{
int i = manager.n_missiles;
struct Missile *m;
while (i-- > 0 && manager.missiles[i].active)
;
m = &manager.missiles[(i > 0) ? (i) : (0)];
m->active = 1;
m->pos.x = x;
m->pos.y = y;
m->spd.x = 0.0f;
m->spd.y = 0.0f;
return m;
}
static void
missile_update(struct Missile *m, struct VecF target)
{
const struct VecF diff = {target.x - m->pos.x, target.y - m->pos.y};
const struct VecF dir = normalize(diff);
/* acceleration */
m->spd.x += dir.x * MISSILE_ACCEL;
m->spd.y += dir.y * MISSILE_ACCEL;
/* friction */
m->spd.x *= 1 - MISSILE_FRICTION;
m->spd.y *= 1 - MISSILE_FRICTION;
/* move */
m->pos.x += m->spd.x;
m->pos.y += m->spd.y;
}
static void
missile_draw(const struct Missile *m)
{
dpixel(m->pos.x + 0.5f, m->pos.y + 0.5f, C_RED);
}

View File

@ -170,7 +170,7 @@ player_update(struct Player *p)
}
void
player_draw(struct Player *p)
player_draw(const struct Player *p)
{
draw_rectangle(C_WHITE, p->pos.x + DRAW_OFF_X, p->pos.y, PLAYER_WIDTH,
PLAYER_HEIGHT);
@ -199,6 +199,13 @@ player_move(struct Player *p, struct Vec spd)
p->pos.y -= sign_y;
}
struct Vec
player_middle(const struct Player *p)
{
return (struct Vec){p->pos.x + PLAYER_WIDTH / 2,
p->pos.y + PLAYER_HEIGHT / 2};
}
static void
reset_speed(struct Player *p, int x, int y)
{

23
src/vec.c Normal file
View File

@ -0,0 +1,23 @@
#include "vec.h"
#include <math.h>
struct VecF
vecf(struct Vec v)
{
return (struct VecF){v.x, v.y};
}
struct Vec
vec(struct VecF v)
{
return (struct Vec){v.x, v.y};
}
struct VecF
normalize(struct VecF v)
{
const float len = sqrt(v.x * v.x + v.y * v.y);
v.x /= len;
v.y /= len;
return v;
}