generalize common bullet motion rules; add some math helpers

This commit is contained in:
Andrei Alexeyev 2019-07-20 16:15:51 +03:00
parent 439d8ea339
commit 2a34f7bad4
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
12 changed files with 114 additions and 22 deletions

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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
View 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
View 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

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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;