generalize common bullet motion rules; add some math helpers
This commit is contained in:
parent
439d8ea339
commit
2a34f7bad4
12 changed files with 114 additions and 22 deletions
|
@ -250,6 +250,11 @@ config.set('TAISEI_BUILDCONF_HAVE_TIMESPEC', have_timespec)
|
|||
config.set('TAISEI_BUILDCONF_HAVE_INT128', cc.sizeof('__int128') == 16)
|
||||
config.set('TAISEI_BUILDCONF_HAVE_LONG_DOUBLE', cc.sizeof('long double') > 8)
|
||||
config.set('TAISEI_BUILDCONF_HAVE_POSIX', have_posix)
|
||||
config.set('TAISEI_BUILDCONF_HAVE_SINCOS', cc.has_function('sincos', dependencies : dep_m))
|
||||
|
||||
if config.get('TAISEI_BUILDCONF_HAVE_SINCOS')
|
||||
config.set('_GNU_SOURCE', true)
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'emscripten'
|
||||
# Emscripten bug: https://github.com/emscripten-core/emscripten/issues/10072
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@alienslab.net>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#include "taisei.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@alienslab.net>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#ifndef IGUARD_coroutine_h
|
||||
|
|
|
@ -85,6 +85,7 @@ taisei_src = files(
|
|||
'list.c',
|
||||
'log.c',
|
||||
'main.c',
|
||||
'move.c',
|
||||
'player.c',
|
||||
'plrmodes.c',
|
||||
'progress.c',
|
||||
|
|
17
src/move.c
Normal file
17
src/move.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT-License
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#include "taisei.h"
|
||||
|
||||
#include "move.h"
|
||||
|
||||
complex move_update(MoveParams *p) {
|
||||
complex v = p->velocity;
|
||||
p->velocity = p->acceleration + p->retention * v;
|
||||
return v;
|
||||
}
|
39
src/move.h
Normal file
39
src/move.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* This software is licensed under the terms of the MIT-License
|
||||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#ifndef IGUARD_move_h
|
||||
#define IGUARD_move_h
|
||||
|
||||
#include "taisei.h"
|
||||
|
||||
/*
|
||||
* Simple generalized projectile movement based on laochailan's idea
|
||||
*/
|
||||
|
||||
#define MOVE_FUNC static inline attr_must_inline MoveParams
|
||||
|
||||
typedef struct MoveParams {
|
||||
complex velocity, acceleration, retention;
|
||||
} MoveParams;
|
||||
|
||||
complex move_update(MoveParams *params);
|
||||
|
||||
MOVE_FUNC move_linear(complex vel) {
|
||||
return (MoveParams) { vel, 0, 1 };
|
||||
}
|
||||
|
||||
MOVE_FUNC move_accelerated(complex vel, complex accel) {
|
||||
return (MoveParams) { vel, accel, 1 };
|
||||
}
|
||||
|
||||
MOVE_FUNC move_asymptotic(complex vel0, complex vel1, complex retention) {
|
||||
// NOTE: retention could be derived by something like: exp(-1 / halflife)
|
||||
return (MoveParams) { vel0, vel1 * (1 - retention), retention };
|
||||
}
|
||||
|
||||
#endif // IGUARD_move_h
|
|
@ -145,6 +145,12 @@ static inline int proj_call_rule(Projectile *p, int t) {
|
|||
ACTION_ACK
|
||||
);
|
||||
}
|
||||
} else if(t >= 0) {
|
||||
p->pos += move_update(&p->move);
|
||||
|
||||
if(p->pos != p->prevpos) {
|
||||
p->angle = carg(p->pos - p->prevpos);
|
||||
}
|
||||
}
|
||||
|
||||
if(/*t == 0 ||*/ t == EVENT_BIRTH) {
|
||||
|
@ -215,6 +221,7 @@ static Projectile* _create_projectile(ProjArgs *args) {
|
|||
p->damage = args->damage;
|
||||
p->damage_type = args->damage_type;
|
||||
p->clear_flags = 0;
|
||||
p->move = args->move;
|
||||
|
||||
if(args->shader_params != NULL) {
|
||||
p->shader_params = *args->shader_params;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "objectpool.h"
|
||||
#include "renderer/api.h"
|
||||
#include "entity.h"
|
||||
#include "move.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define PROJ_DEBUG
|
||||
|
@ -82,6 +83,7 @@ struct Projectile {
|
|||
ShaderProgram *shader;
|
||||
Sprite *sprite;
|
||||
ProjPrototype *proto;
|
||||
MoveParams move;
|
||||
Color color;
|
||||
ShaderCustomParams shader_params;
|
||||
BlendMode blend;
|
||||
|
@ -122,6 +124,7 @@ typedef struct ProjArgs {
|
|||
cmplx pos;
|
||||
cmplx size; // affects default draw order, out-of-viewport culling, and grazing
|
||||
cmplx collision_size; // affects collision with player (TODO: make this work for player projectiles too?)
|
||||
MoveParams move;
|
||||
ProjType type;
|
||||
ProjFlags flags;
|
||||
BlendMode blend;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@alienslab.net>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#include "taisei.h"
|
||||
|
@ -37,13 +37,13 @@ TASK(laserize_proj, { Projectile *p; int t; }) {
|
|||
kill_projectile(ARGS.p);
|
||||
|
||||
complex aim = 12 * cexp(I * a);
|
||||
create_laserline(pos, aim, 20, 40, &clr);
|
||||
create_laserline(pos, aim, 60, 80, &clr);
|
||||
|
||||
PROJECTILE(
|
||||
.pos = pos,
|
||||
.proto = pp_ball,
|
||||
.color = &clr,
|
||||
.timeout = 20,
|
||||
.timeout = 60,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,7 @@ TASK(wait_event_test, { Enemy *e; int rounds; int delay; int cnt; int cnt_inc; }
|
|||
.pos = pos,
|
||||
.proto = pp_crystal,
|
||||
.color = RGBA(i / (double)ARGS.cnt, 0.0, 1.0 - i / (double)ARGS.cnt, 0.0),
|
||||
.rule = asymptotic,
|
||||
.args = { 2 * aim, 5 },
|
||||
.move = move_asymptotic(12 * aim, 2 * aim, 0.8),
|
||||
);
|
||||
|
||||
WAIT(1);
|
||||
|
@ -107,7 +106,7 @@ TASK_WITH_FINALIZER(test_enemy, {
|
|||
ARGS.for_finalizer.x++;
|
||||
|
||||
// wander around for a bit...
|
||||
for(int i = 0; i < 20; ++i) {
|
||||
for(int i = 0; i < 60; ++i) {
|
||||
e->pos += ARGS.dir;
|
||||
YIELD;
|
||||
}
|
||||
|
@ -116,22 +115,25 @@ TASK_WITH_FINALIZER(test_enemy, {
|
|||
WAIT(10);
|
||||
|
||||
// pew pew!!!
|
||||
int pcount = 10 + 10 * frand();
|
||||
complex aim = 3 * cnormalize(global.plr.pos - e->pos);
|
||||
int pcount = 120;
|
||||
|
||||
for(int i = 0; i < pcount; ++i) {
|
||||
complex aim = global.plr.pos - e->pos;
|
||||
aim *= 5 * cexp(I*M_PI*0.1*nfrand()) / cabs(aim);
|
||||
for(int j = -1; j < 2; j += 2) {
|
||||
double a = j * M_PI * 0.1 * psin(20 * (2 * global.frames + i * 10));
|
||||
|
||||
Projectile *p = PROJECTILE(
|
||||
.pos = e->pos,
|
||||
.proto = pp_rice,
|
||||
.color = RGBA(1.0, 0.0, i / (pcount - 1.0), 0.0),
|
||||
.rule = linear,
|
||||
.args = { aim },
|
||||
);
|
||||
Projectile *p = PROJECTILE(
|
||||
.pos = e->pos,
|
||||
.proto = pp_rice,
|
||||
.color = RGBA(1.0, 0.0, i / (pcount - 1.0), 0.0),
|
||||
.move = move_asymptotic(aim * 4 * cdir(a + M_PI), aim * cdir(-a * 2), 0.9),
|
||||
.max_viewport_dist = 128,
|
||||
);
|
||||
|
||||
INVOKE_TASK(laserize_proj, p, 30);
|
||||
INVOKE_TASK(laserize_proj, p, 40);
|
||||
}
|
||||
|
||||
WAIT(3);
|
||||
WAIT(2);
|
||||
}
|
||||
|
||||
// keep wandering, randomly
|
||||
|
@ -153,7 +155,7 @@ TASK(stage_main, { int ignored; }) {
|
|||
|
||||
for(;;) {
|
||||
INVOKE_TASK(test_enemy, 9000, CMPLX(VIEWPORT_W, VIEWPORT_H) * 0.5, 3*I);
|
||||
WAIT(500);
|
||||
WAIT(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* See COPYING for further information.
|
||||
* ---
|
||||
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@alienslab.net>.
|
||||
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
||||
*/
|
||||
|
||||
#ifndef IGUARD_stages_corotest_h
|
||||
|
|
|
@ -91,6 +91,22 @@ void capproach_asymptotic_p(cmplx *val, cmplx target, double rate, double epsilo
|
|||
*val = capproach_asymptotic(*val, target, rate, epsilon);
|
||||
}
|
||||
|
||||
cmplx cnormalize(cmplx c) {
|
||||
return c / cabs(c);
|
||||
}
|
||||
|
||||
cmplx cdir(double angle) {
|
||||
// this is faster than cexp(I*angle)
|
||||
|
||||
#ifdef TAISEI_BUILDCONF_HAVE_SINCOS
|
||||
double s, c;
|
||||
sincos(angle, &s, &c);
|
||||
return CMPLX(c, s);
|
||||
#else
|
||||
return CMPLX(cos(angle), sin(angle));
|
||||
#endif
|
||||
}
|
||||
|
||||
double psin(double x) {
|
||||
return 0.5 + 0.5 * sin(x);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ cmplx capproach_asymptotic(cmplx val, cmplx target, double rate, double epsilon)
|
|||
void approach_asymptotic_p(double *val, double target, double rate, double epsilon);
|
||||
void fapproach_asymptotic_p(float *val, float target, float rate, float epsilon);
|
||||
void capproach_asymptotic_p(cmplx *val, cmplx target, double rate, double epsilon);
|
||||
cmplx cnormalize(cmplx c) attr_const;
|
||||
cmplx cdir(double angle) attr_const;
|
||||
double psin(double) attr_const;
|
||||
int sign(double) attr_const;
|
||||
double swing(double x, double s) attr_const;
|
||||
|
|
Loading…
Reference in a new issue