ref: 94f786ad93b4e5f1f3158062f4a0400c6b1b80df
parent: a1c6005292984c6c2c6327cf4f6dfa1b5b2e72cb
author: qwx <qwx@sciops.net>
date: Sat Aug 29 07:38:46 EDT 2020
add acceleration, deceleration and turning speed halt distance is also there, but unused. current heuristic for deceleration seems to work alright.
--- a/dat.h
+++ b/dat.h
@@ -48,6 +48,8 @@
double g;
double Δg;
double h;
+ double len;
+ double Δlen;
int step;
int dir;
Node *from;
@@ -98,10 +100,13 @@
Attack *atk[2];
int hp;
int def;
- int speed;
int vis;
int cost[Nresource];
int time;
+ double speed;
+ double accel;
+ double halt;
+ double turn;
Obj **spawn;
int nspawn;
};
@@ -110,6 +115,7 @@
int goalblocked;
int npatherr;
int npathbuf;
+ double pathlen;
Point *paths;
Point *pathp;
Point *pathe;
@@ -117,14 +123,15 @@
struct Mobj{
Obj *o;
Pics *pics;
- int θ;
Point;
int px;
int py;
int subpx;
int subpy;
+ double θ;
+ double Δθ;
+ int Δθs;
Path;
- int Δθ;
double u;
double v;
double speed;
--- a/drw.c
+++ b/drw.c
@@ -269,9 +269,10 @@
Pics *pp;
Pic *p;
+ θ = mo->θ * 32.0 / 256;
pp = mo->pics;
switch(pp->nr){
- case 17: θ = rot17[mo->θ]; break;
+ case 17: θ = rot17[θ]; break;
default: θ = 0; break;
}
if(notshadow){
--- a/fs.c
+++ b/fs.c
@@ -230,6 +230,7 @@
vunpack(char **fld, char *fmt, va_list a)
{
int n;
+ double d;
char *s;
Attack *atk;
Resource *r;
@@ -244,6 +245,11 @@
sysfatal("vunpack: illegal positive integer %d", n);
*va_arg(a, int*) = n;
break;
+ case 'f':
+ if((d = strtod(*fld++, nil)) < 0.0)
+ sysfatal("vunpack: illegal positive double %f", d);
+ *va_arg(a, double*) = d;
+ break;
case 'a':
s = *fld++;
if(*s == 0){
@@ -389,10 +395,14 @@
obj = emalloc(nobj * sizeof *obj);
o = obj + tab->row;
o->name = estrdup(*fld++);
- unpack(fld, "dddddddddddaa", &o->f, &o->w, &o->h,
- &o->hp, &o->def, &o->speed, &o->vis,
+ unpack(fld, "ddddddddddaaffff", &o->f, &o->w, &o->h,
+ &o->hp, &o->def, &o->vis,
o->cost, o->cost+1, o->cost+2, &o->time,
- o->atk, o->atk+1);
+ o->atk, o->atk+1, &o->speed, &o->accel, &o->halt, &o->turn);
+ o->accel /= 256.0;
+ o->halt /= 256.0;
+ /* halting distance in path node units */
+ o->halt /= Tlsubwidth;
if(o->w < 1 || o->h < 1)
sysfatal("readobj: %s invalid dimensions %d,%d", o->name, o->w, o->h);
}
@@ -433,7 +443,7 @@
Table table[] = {
{"mapobj", readmapobj, 4, &nobjp},
- {"obj", readobj, 14, &nobj},
+ {"obj", readobj, 17, &nobj},
{"attack", readattack, 4, &nattack},
{"resource", readresource, 2, &nresource},
{"spawn", readspawn, -1, nil},
--- a/map.c
+++ b/map.c
@@ -102,7 +102,7 @@
mo->o = o;
mo->f = o->f;
mo->hp = o->hp;
- mo->θ = nrand(Nrot);
+ mo->θ = frand() * 256;
updatemap(mo);
return mo;
}
--- a/path.c
+++ b/path.c
@@ -155,6 +155,7 @@
return nil;
if(Δvg == 0 && (Δug < 0) ^ (Δug2 < 0)){
b->Δg = steps - abs(Δug2);
+ b->Δlen = b->Δg;
return b;
}
if(end)
@@ -164,6 +165,7 @@
n->x = x;
n->y = y;
n->Δg = steps;
+ n->Δlen = steps;
return n;
}
@@ -198,6 +200,7 @@
n->x = x;
n->y = y;
n->Δg = steps;
+ n->Δlen = steps * SQRT2;
return n;
}
@@ -343,6 +346,7 @@
n->from = x;
n->g = g;
n->h = octdist(n, b);
+ n->len = x->len + n->Δlen;
n->open = 1;
n->step = x->step + 1;
pushqueue(n, &queue);
@@ -349,6 +353,7 @@
}else if(Δg > 0){
n->from = x;
n->step = x->step + 1;
+ n->len = x->len + n->Δlen;
n->g -= Δg;
decreasekey(n->p, Δg, &queue);
}
@@ -372,6 +377,7 @@
mo->npathbuf * sizeof mo->paths);
mo->npathbuf = n->step;
}
+ mo->pathlen = n->len;
p = mo->paths + n->step;
mo->pathe = p--;
for(; n!=a; n=n->from){
--- a/sce/sce.db
+++ b/sce/sce.db
@@ -5,11 +5,11 @@
# attack: name, dmg, range, cool
attack,fusion cutter,5,1,15
attack,spines,5,1,22
-# obj: name, flags, w, h, hp, def, speed, vis, cost[3], time, attack[2]
-obj,scv,3,4,4,60,0,5,7,1,50,0,20,fusion cutter,
-obj,drone,1,4,4,40,0,5,7,1,50,0,20,spines,
-obj,control,8,16,12,1500,1,0,1,10,400,0,1800,,
-obj,hatchery,8,16,12,1250,1,0,1,10,300,0,1800,,
+# obj: name, flags, w, h, hp, def, vis, cost[3], time, attack[2], speed, accel, halt, turn
+obj,scv,3,4,4,60,0,7,1,50,0,20,fusion cutter,,4.97,67,12227,40
+obj,drone,1,4,4,40,0,7,1,50,0,20,spines,,4.97,67,12227,40
+obj,control,8,16,12,1500,1,1,10,400,0,1800,,,0,0,0,0
+obj,hatchery,8,16,12,1250,1,1,10,300,0,1800,,,0,0,0,0
# spawn: objname, [obj..]
spawn,control,scv
# spr: objname, flags (PF enum), rotations, [frame..]
--- a/sim.c
+++ b/sim.c
@@ -52,11 +52,11 @@
markmobj(mo, 1);
}
-static int
+static double
facemobj(Point p, Mobj *mo)
{
int dx, dy;
- double vx, vy, θ, d;
+ double vx, vy, d, θ, θ256, Δθ;
dx = p.x - mo->x;
dy = p.y - mo->y;
@@ -63,14 +63,24 @@
d = sqrt(dx * dx + dy * dy);
vx = dx / d;
vy = dy / d;
- mo->u = vx;
- mo->v = vy;
+ /* angle in radians [0;2π[ with 0 facing north */
θ = atan2(vy, vx) + PI / 2;
if(θ < 0)
θ += 2 * PI;
else if(θ >= 2 * PI)
θ -= 2 * PI;
- return (θ / (2 * PI) * 360) / (90. / (Nrot / 4));
+ /* movement calculations use values in [0;256[, drawing in [0;32[ */
+ θ256 = θ * 256.0 / (2 * PI);
+ mo->u = vx;
+ mo->v = vy;
+ Δθ = θ256 - mo->θ;
+ if(Δθ <= -256 / 2)
+ Δθ += 256;
+ else if(Δθ >= 256 / 2)
+ Δθ -= 256;
+ mo->Δθs = Δθ < 0 ? -1: 1;
+ mo->Δθ = fabs(Δθ);
+ return θ256;
}
static void
@@ -85,16 +95,8 @@
static void
nextmove(Mobj *mo)
{
- int Δθ;
-
resetcoords(mo);
- Δθ = facemobj(*mo->pathp, mo) - mo->θ;
- if(Δθ <= -Nrot / 2)
- Δθ += Nrot;
- else if(Δθ >= Nrot / 2)
- Δθ -= Nrot;
- mo->Δθ = Δθ;
- mo->speed = mo->o->speed;
+ facemobj(*mo->pathp, mo);
}
static int
@@ -122,6 +124,7 @@
}
setgoal(&p, mo, block);
if(repath(p, mo) < 0){
+ mo->speed = 0.0;
dprint("move to %d,%d: %r\n", p.x, p.y);
return -1;
}
@@ -144,25 +147,50 @@
return 0;
}
-static void
+static int
tryturn(Mobj *mo)
{
- int Δθ;
+ int r;
+ double Δθ;
- if(mo->Δθ < 0)
- Δθ = mo->Δθ < -2 ? -2 : mo->Δθ;
- else
- Δθ = mo->Δθ > 2 ? 2 : mo->Δθ;
- mo->θ = mo->θ + Δθ & Nrot - 1;
+ r = 1;
+ if(mo->Δθ <= mo->o->turn){
+ r = 0;
+ Δθ = mo->Δθ;
+ }else
+ Δθ = mo->o->turn;
+ mo->θ += mo->Δθs * Δθ;
+ if(mo->θ < 0)
+ mo->θ += 256;
+ else if(mo->θ >= 256)
+ mo->θ -= 256;
mo->Δθ -= Δθ;
+ return r;
}
+static void
+updatespeed(Mobj *mo)
+{
+ if(mo->pathlen < (mo->speed / 8) * (mo->speed / 8) / 2 / (mo->o->accel / 8)){
+ mo->speed -= mo->o->accel;
+ if(mo->speed < 0.0)
+ mo->speed = 0.0;
+ }else if(mo->speed < mo->o->speed){
+ mo->speed += mo->o->accel;
+ if(mo->speed > mo->o->speed)
+ mo->speed = mo->o->speed;
+ }
+}
+
static int
trymove(Mobj *mo)
{
- int x, y, sx, sy, Δx, Δy, Δu, Δv, Δrx, Δry, Δpx, Δpy;
+ int x, y, px, py, sx, sy, Δx, Δy, Δu, Δv, Δrx, Δry, Δpx, Δpy;
+ double dx, dy;
markmobj(mo, 0);
+ px = mo->px;
+ py = mo->py;
sx = mo->subpx;
sy = mo->subpy;
Δu = mo->u * (1 << Subpxshift);
@@ -169,8 +197,8 @@
Δv = mo->v * (1 << Subpxshift);
Δx = abs(Δu);
Δy = abs(Δv);
- Δrx = Δx * mo->speed;
- Δry = Δy * mo->speed;
+ Δrx = fabs(mo->u * mo->speed) * (1 << Subpxshift);
+ Δry = fabs(mo->v * mo->speed) * (1 << Subpxshift);
Δpx = abs((mo->pathp->x * Tlsubwidth << Subpxshift) - sx);
Δpy = abs((mo->pathp->y * Tlsubwidth << Subpxshift) - sy);
if(Δpx < Δrx)
@@ -213,6 +241,11 @@
mo->y = mo->py / Tlsubheight;
}
markmobj(mo, 1);
+ dx = mo->px - px;
+ dx *= dx;
+ dy = mo->py - py;
+ dy *= dy;
+ mo->pathlen -= sqrt(dx + dy) / Tlsubwidth;
return 0;
end:
werrstr("trymove: can't move to %d,%d", x, y);
@@ -219,25 +252,37 @@
mo->subpx = mo->px << Subpxshift;
mo->subpy = mo->py << Subpxshift;
markmobj(mo, 1);
+ dx = mo->px - px;
+ dx *= dx;
+ dy = mo->py - py;
+ dy *= dy;
+ mo->pathlen -= sqrt(dx + dy) / Tlsubwidth;
return -1;
}
+static int
+domove(Mobj *mo)
+{
+ int r;
+
+ updatespeed(mo);
+ unlinkmobj(mo->mapp);
+ r = trymove(mo);
+ linktomap(mo);
+ return r;
+}
+
static void
stepmove(Mobj *mo)
{
- int r, n;
+ int n;
n = 0;
restart:
n++;
- if(mo->Δθ != 0){
- tryturn(mo);
+ if(tryturn(mo))
return;
- }
- unlinkmobj(mo->mapp);
- r = trymove(mo);
- linktomap(mo);
- if(r < 0){
+ if(domove(mo) < 0){
if(n > 1){
fprint(2, "stepmove: %s %#p bug inducing infinite loop!\n",
mo->o->name, mo);
@@ -247,6 +292,7 @@
if(repath(mo->target, mo) < 0){
dprint("stepmove: %s %#p moving towards target: %r\n",
mo->o->name, mo);
+ mo->speed = 0.0;
return;
}
goto restart;
@@ -258,6 +304,7 @@
return;
}else if(mo->x == mo->target.x && mo->y == mo->target.y){
mo->npatherr = 0;
+ mo->speed = 0.0;
freemove(mo);
return;
}
@@ -266,6 +313,7 @@
if(mo->goalblocked && isblocked(mo->target.x, mo->target.y, mo->o)){
dprint("stepmove: %s %#p goal still blocked, stopping\n",
mo->o->name, mo);
+ mo->speed = 0.0;
freemove(mo);
return;
}
@@ -274,6 +322,7 @@
dprint("stepmove: %s %#p trying to find target: %r\n",
mo->o->name, mo);
mo->npatherr = 0;
+ mo->speed = 0.0;
freemove(mo);
}
}