diff options
-rw-r--r-- | build/Arena.exe | bin | 179757 -> 183626 bytes | |||
-rw-r--r-- | build/army/3000 hvy mg.txt | bin | 0 -> 25656 bytes | |||
-rw-r--r-- | build/army/mins.txt | bin | 25656 -> 25656 bytes | |||
-rw-r--r-- | build/army/new army 0.txt | bin | 25656 -> 25656 bytes | |||
-rw-r--r-- | build/army/new army.txt | bin | 25656 -> 25656 bytes | |||
-rw-r--r-- | build/content/templates/default.txt | 42 | ||||
-rw-r--r-- | design/notes.txt | 3 | ||||
-rw-r--r-- | gst/fxs.c | 98 | ||||
-rw-r--r-- | gst/fxs.h | 32 | ||||
-rw-r--r-- | gst/gst.c | 111 | ||||
-rw-r--r-- | gst/gst.h | 2 | ||||
-rw-r--r-- | gst/units.c | 40 | ||||
-rw-r--r-- | hud/hud.c | 16 |
13 files changed, 273 insertions, 71 deletions
diff --git a/build/Arena.exe b/build/Arena.exe Binary files differindex fc850b2..00ecf39 100644 --- a/build/Arena.exe +++ b/build/Arena.exe diff --git a/build/army/3000 hvy mg.txt b/build/army/3000 hvy mg.txt Binary files differnew file mode 100644 index 0000000..a6ee9b3 --- /dev/null +++ b/build/army/3000 hvy mg.txt diff --git a/build/army/mins.txt b/build/army/mins.txt Binary files differindex 7ff2597..8308a2d 100644 --- a/build/army/mins.txt +++ b/build/army/mins.txt diff --git a/build/army/new army 0.txt b/build/army/new army 0.txt Binary files differindex 65658ce..ff5ec8c 100644 --- a/build/army/new army 0.txt +++ b/build/army/new army 0.txt diff --git a/build/army/new army.txt b/build/army/new army.txt Binary files differindex 5d02299..a658fff 100644 --- a/build/army/new army.txt +++ b/build/army/new army.txt diff --git a/build/content/templates/default.txt b/build/content/templates/default.txt index d70c887..110057a 100644 --- a/build/content/templates/default.txt +++ b/build/content/templates/default.txt @@ -40,13 +40,43 @@ "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }, { - "name": "fortissimo", + "name": "ndouble hvy railgun", "chassis": "14", - "brain": "0", - "battery": "5", - "weapons": [ 28, 13, 14, 2, -1, -1, -1, -1 ], - "armor": [ 0, 2, 6, 3, 7, 10, -1, -1 ], - "augs": [ 1, 6, 15, 8, 7, 11, -1, -1 ], + "brain": "4", + "battery": "4", + "weapons": [ 27, 27, -1, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "nameless", + "chassis": "14", + "brain": "1", + "battery": "0", + "weapons": [ 16, 37, -1, -1, -1, -1, -1, -1 ], + "armor": [ 5, 8, 4, 8, 8, 10, 7, -1 ], + "augs": [ 4, 0, 13, 11, 9, 2, -1, -1 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "gatling", + "chassis": "5", + "brain": "5", + "battery": "0", + "weapons": [ 0, 0, -1, -1, -1, -1, -1, -1 ], + "armor": [ -1, -1, -1, -1, -1, -1, -1, -1 ], + "augs": [ 7, 7, 7, 7, 7, 7, 7, 7 ], + "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + }, + { + "name": "idiot", + "chassis": "14", + "brain": "4", + "battery": "1", + "weapons": [ 36, 22, 21, -1, -1, -1, -1, -1 ], + "armor": [ 4, 7, 5, 6, 2, 4, -1, -1 ], + "augs": [ 4, 8, 7, 15, 10, 7, 13, -1 ], "levels": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] } ]
\ No newline at end of file diff --git a/design/notes.txt b/design/notes.txt index 6528db6..12b60d5 100644 --- a/design/notes.txt +++ b/design/notes.txt @@ -1,5 +1,6 @@ tasks: +[ ] unify gui design (issued on 05:03:21) [ ] implement aoe (issued on 02:03:21) [ ] implement knockback (issued on 02:03:21) [ ] implement stun (issued on 02:03:21) @@ -17,7 +18,7 @@ tasks: [ ] implement 3d units (issued on 18:02:21) [ ] design component sprites (issued on 18:02:21) [ ] implement sound (issued on 18:02:21) -[ ] implement component aoe bonus (issued on 02:03:21) +[ ] implement component aoe effects (issued on 02:03:21) [x] implement edit unit directly (issued on 18:02:21, done on 04:03:21) [x] implement rm template (issued on 04:03:21, done on 04:03:21) @@ -1,5 +1,6 @@ #include <stdlib.h> #include <stdio.h> +#include <math.h> #include "../umath/vec.h" @@ -7,31 +8,105 @@ #include "units.h" void fx_init (fxs *fx) { - fx->bullets = (bullet*)malloc(sizeof(bullet)*1024); + fx->bullets = (bullet*)malloc(sizeof(bullet)*FXS_BULLET_MAX); fx->bulletslen = 0; + fx->explosions = (explosion*)malloc(sizeof(explosion)*FXS_EXPLOSION_MAX); + fx->explosionslen = 0; } void fx_add_bullet (fxs *fx, bullet *b) { - if (fx->bulletslen >= 1024-1) return; + if (fx->bulletslen >= FXS_BULLET_MAX-1) return; fx->bullets[fx->bulletslen] = *b; fx->bulletslen++; } +void fx_spread_to_head (float spread, float head[]) { + head[0] = 1-spread; if (spread<0.5) head[0] = spread; + head[1] = 1-spread*2; + vec2_norm(head); +} + +/* + * param: pos is the center of the explosion + * param: vel is the heading of the explosion + * param: force is added to vel and scaled by mass + * param: spread [0, 1] is half the angle of the explosion + * param: speed [0, inf] is the initial speed + */ +void fx_explosion_init (fxs *fx, explosion *e, + float pos[], float vel[], float color[], float force[], + float spread, float speed, int n, float time, float lifetime) +{ + float normvel[2] = { vel[0], vel[1] }; vec2_norm(normvel); + float perpvel[2] = { normvel[1], -normvel[0] }; + e->pos[0] = pos[0]; e->pos[1] = pos[1]; + e->partslen = n; + e->force[0] = force[0]; e->force[1] = force[1]; + e->starttime = time; + e->friction = 0.95; + for (int j=0; j<n; j++) { + particle *p = e->parts+j; + float sample = rand()%1000/1000.0 * spread; + float head[2]; fx_spread_to_head(sample, head); + if (j%2 == 0) head[0] *= -1; + float dir[2] = { + -head[0]*normvel[1] - head[1]*perpvel[1], + head[0]*normvel[0] + head[1]*perpvel[0] + }; + p->lifetime = lifetime; + p->mass = 1; + p->pos[0] = pos[0]; p->pos[1] = pos[1]; + p->vel[0] = dir[0]; p->vel[1] = dir[1]; + vec2_mul(p->vel, p->vel, speed+(rand()%1000)/1000.0*speed/2); + p->color[0] = color[0]; + p->color[1] = color[1]; + p->color[2] = color[2]; + } +} + +void fx_add_explosion (fxs *fx, explosion *e) { + if (fx->explosionslen >= FXS_EXPLOSION_MAX-1) return; + fx->explosions[fx->explosionslen] = *e; + fx->explosionslen++; +} + void fx_process (fxs *fx, float time) { for (int i=0; i<fx->bulletslen; i++) { bullet *b = fx->bullets+i; + if (b->starttime > time) continue; if (time > b->endtime) { // remove by replacing with last, dont care for order *b = fx->bullets[fx->bulletslen-1]; fx->bulletslen--; } } + + for (int i=0; i<fx->explosionslen; i++) { + explosion *e = fx->explosions+i; + if (e->starttime > time) continue; + int sum = e->partslen; + for (int j=0; j<e->partslen; j++) { + if (e->starttime + e->parts[j].lifetime >= time) { + vec2_add(e->parts[j].pos, e->parts[j].pos, e->parts[j].vel); + float forcemass[2]; + vec2_mul(forcemass, e->force, e->parts[j].mass); + vec2_add(e->parts[j].vel, e->parts[j].vel, forcemass); + vec2_mul(e->parts[j].vel, e->parts[j].vel, e->friction); + } else { sum -= 1; } + } + if (sum == 0) { + // remove by replacing with last, dont care for order + *e = fx->explosions[fx->explosionslen-1]; + fx->explosionslen--; + } + } } void fx_render (SDL_Renderer *rend, fxs *fx, float cam[], float time) { for (int i=0; i<fx->bulletslen; i++) { bullet *b = fx->bullets+i; + if (b->starttime > time) continue; float travel_time = b->endtime - b->starttime; float interval_time = time - b->starttime; float amt = interval_time / travel_time; @@ -46,10 +121,7 @@ void fx_render (SDL_Renderer *rend, fxs *fx, float cam[], float time) { if (dist < 10) { mag = dist; } vec2_norm(head); vec2_mul(head, head, mag); SDL_SetRenderDrawColor(rend, - b->color[0], - b->color[1], - b->color[2], - 255); + b->color[0], b->color[1], b->color[2], 255); SDL_RenderDrawLine(rend, -cam[0] + pos[0], -cam[1] + pos[1], @@ -57,4 +129,18 @@ void fx_render (SDL_Renderer *rend, fxs *fx, float cam[], float time) { -cam[1] + pos[1] + head[1] ); } + + for (int i=0; i<fx->explosionslen; i++) { + explosion *e = fx->explosions+i; + if (e->starttime > time) continue; + for (int j=0; j<e->partslen; j++) { + particle *p = e->parts+j; + if (e->starttime + p->lifetime >= time) { + SDL_SetRenderDrawColor(rend, + p->color[0], p->color[1], p->color[2], 255); + SDL_RenderDrawPoint(rend, + -cam[0] + p->pos[0], -cam[1] + p->pos[1]); + } + } + } } @@ -3,22 +3,52 @@ #include <SDL2/SDL.h> +#define FXS_BULLET_MAX 4096 +#define FXS_EXPLOSION_MAX 2048 + typedef struct { float from[2]; float to[2]; float starttime; float endtime; float size; - int color[3]; + float color[3]; } bullet; typedef struct { + float pos[2]; + float vel[2]; + float color[3]; + float size; + float mass; + float lifetime; +} particle; + +typedef struct { + float pos[2]; + float force[2]; + float friction; + particle parts[32]; + int partslen; + float starttime; +} explosion; + +typedef struct { bullet *bullets; int bulletslen; + explosion *explosions; + int explosionslen; } fxs; void fx_init (fxs *fx); + void fx_add_bullet (fxs *fx, bullet *b); + +void fx_explosion_init (fxs *fx, explosion *e, + float pos[], float vel[], float color[], float force[], + float spread, float speed, int n, float time, float lifetime); +void fx_add_explosion (fxs *fx, explosion *e); + void fx_process (fxs *fx, float time); void fx_render (SDL_Renderer *rend, fxs *fx, float cam[], float time); @@ -4,6 +4,7 @@ #include <float.h> #include "gst.h" +#include "../umath/vec.h" void gst_init (gamestate *gst) { map_init(&gst->map_editor, MAXMAP, MAXMAP, 32); @@ -33,11 +34,9 @@ void gst_get_maparmy(gamestate *gst, map **m, army **ar) { } } -void gst_lastpos (gamestate *gst) { - for (int i=0; i<gst->ar.uslen; i++) { - gst->ar_lastpos[i][0] = gst->ar.us[i].pos[0]; - gst->ar_lastpos[i][1] = gst->ar.us[i].pos[1]; - } +void gst_ar_past_cycle (gamestate *gst) { + gst->ar_past[1] = gst->ar_past[0]; + gst->ar_past[0] = gst->ar; } void gst_compute_stats (gamestate *gst, infos *info) { @@ -48,7 +47,6 @@ void gst_compute_stats (gamestate *gst, infos *info) { void gst_tobattle (gamestate *gst, infos *info) { if (gst->playernum == 1) { - //info_load_army(gst->army_bp+1, "army"); gst->army_bp[1] = gst->army_bp[0]; gst->playernum = 2; } @@ -79,7 +77,7 @@ void gst_tobattle (gamestate *gst, infos *info) { } gst_compute_stats(gst, info); - gst_lastpos(gst); + gst_ar_past_cycle(gst); gst->starttime = FLT_MAX; gst->turn = 0; gst->coveredtime = 0; @@ -117,21 +115,62 @@ void gst_spawn_bullets (gamestate *gst, fxs *fx, a_dmg dmgs[], int dmgslen, unit *u = ar->us+i; if (dmgs[j].u == u) { unit *t = dmgs[j].t; - b.from[0] = u->pos[0]+16; - b.from[1] = u->pos[1]+16; - b.to[0] = t->pos[0]+16; - b.to[1] = t->pos[1]+16; float n = (float)curr[i]/counts[i]; - float travel_time = 0.1; + + float u_past_x = gst->ar_past[1].us[i].pos[0]; + float u_past_y = gst->ar_past[1].us[i].pos[1]; + float u_pres_x = gst->ar_past[0].us[i].pos[0]; + float u_pres_y = gst->ar_past[0].us[i].pos[1]; + + int t_i = 0; + for (int k=0; k<ar->uslen; k++) { + if (ar->us+k == t) { t_i = k; break; } + } + + float t_past_x = gst->ar_past[1].us[t_i].pos[0]; + float t_past_y = gst->ar_past[1].us[t_i].pos[1]; + float t_pres_x = gst->ar_past[0].us[t_i].pos[0]; + float t_pres_y = gst->ar_past[0].us[t_i].pos[1]; + + // interpolate from the past + b.from[0] = u_pres_x*(n) + u_past_x*(1-n)+16 +rand()%8-4; + b.from[1] = u_pres_y*(n) + u_past_y*(1-n)+16 +rand()%8-4; + b.to[0] = t_pres_x*(n) + t_past_x*(1-n)+16 +rand()%16-8; + b.to[1] = t_pres_y*(n) + t_past_y*(1-n)+16 +rand()%16-8; + + float travel_time = 0.3; float shot_time = time + n*gst->turnspeed; b.starttime = shot_time; b.endtime = shot_time + travel_time; - if (u->owner == 0) { - b.color[0] = 0; b.color[1] = 255; b.color[2] = 0; - } else { - b.color[0] = 255; b.color[1] = 0; b.color[2] = 0; - } + + float colors[2][3] = { {0,255,0}, {255,0,0} }; + int selcol = 0; + + if (u->owner == 0) { selcol = 0; } + else { selcol = 1; } + b.color[0] = colors[selcol][0]; + b.color[1] = colors[selcol][1]; + b.color[2] = colors[selcol][2]; fx_add_bullet(fx, &b); + + + { /* shooting particles */ + float vel[2]; vec2_sub(vel, b.to, b.from); + float force[2] = { 0, 0 }; + explosion e; + fx_explosion_init(fx, &e, b.from, vel, colors[selcol], + force, 0.1, 2, 4, b.starttime, 0.2); + fx_add_explosion(fx, &e); + } + + { /* hit particles */ + float vel[2]; vec2_sub(vel, b.to, b.from); + float force[2] = { 0, 0 }; + explosion e; + fx_explosion_init(fx, &e, b.to, vel, colors[1-selcol], + force, 0.15, 4, 8, b.endtime, 0.8); + fx_add_explosion(fx, &e); + } curr[i] ++; } } @@ -154,7 +193,6 @@ int gst_check_victory (gamestate *gst) { } void gst_next_turn (gamestate *gst, infos *info, fxs *fx, float t) { - gst_lastpos(gst); gst->coveredtime += gst->turnspeed; gst->turn ++; map *m; army *ar; @@ -170,6 +208,7 @@ void gst_next_turn (gamestate *gst, infos *info, fxs *fx, float t) { if (gst->turn_until_finish <= 0) { gst->over = 1; } + gst_ar_past_cycle(gst); gst_spawn_bullets(gst, fx, dmgs, fire, t); } @@ -214,24 +253,34 @@ void gst_render (SDL_Renderer *rend, SDL_Texture *txsprites, txtd *textd, amt = (amt / gst->turnspeed) + 1; if (amt > 1) amt = 1; if (amt < 0) amt = 0; // clamping away fuzzyness + army *past = ar; + army *present = ar; + if (gst->state == 1) { + past = gst->ar_past +1; + present = gst->ar_past +0; + } + // render units for (int i=0; i<ar->uslen; i++) { - if (ar->us[i].hp <= 0) continue; - float present_x = ar->us[i].pos[0]; - float present_y = ar->us[i].pos[1]; + if (present->us[i].hp <= 0) continue; + + float past_x = past->us[i].pos[0]; + float past_y = past->us[i].pos[1]; + + float present_x = present->us[i].pos[0]; + float present_y = present->us[i].pos[1]; - float x = present_x, y = present_y; - if (gst->state == 1) { - x = present_x*(amt) + gst->ar_lastpos[i][0]*(1-amt); - y = present_y*(amt) + gst->ar_lastpos[i][1]*(1-amt); - } + float x = present_x*(amt) + past_x*(1-amt); + float y = present_y*(amt) + past_y*(1-amt); - SDL_Rect srcRect = { ar->us[i].info.chassis*ts, ts, ts, ts }; + SDL_Rect srcRect = { + present->us[i].info.chassis*ts, ts, ts, ts }; SDL_Rect dstRect = { (int)x-posx, (int)y-posy, ts, ts }; SDL_RenderCopy(rend, txsprites, &srcRect, &dstRect); - stats_unit base; stats_unit_compute(info, &ar->us[i].info, &base); - float amt = ar->us[i].hp / base.frame.hp; + stats_unit base; + stats_unit_compute(info, &present->us[i].info, &base); + float amt = present->us[i].hp / base.frame.hp; SDL_Rect hprect = { (int)x-posx, (int)y-posy+ts-5, ts*amt, 6 }; @@ -240,12 +289,12 @@ void gst_render (SDL_Renderer *rend, SDL_Texture *txsprites, txtd *textd, SDL_RenderFillRect(rend, &hprect); SDL_SetTextureColorMod(textd->tex_small, sw*100, 100*(1-sw), 0); - char shp[32]; sprintf(shp, "%.0f", ar->us[i].hp); + char shp[32]; sprintf(shp, "%.0f", present->us[i].hp); float php[2] = { (int)x-posx, (int)y-posy+ts-5 }; render_text_small(rend, shp, php, textd); SDL_SetTextureColorMod(textd->tex_small, 255, 160, 0); - char sch[32]; sprintf(sch, "%.0f", ar->us[i].charge); + char sch[32]; sprintf(sch, "%.0f", present->us[i].charge); float pch[2] = { (int)x-posx, (int)y-posy+ts+1 }; render_text_small(rend, sch, pch, textd); SDL_SetTextureColorMod(textd->tex_small, 0, 0, 0); @@ -20,7 +20,7 @@ typedef struct { int playernum; map map_battle; army ar; - float ar_lastpos[MAXUNITS][2]; + army ar_past[2]; stats_unit ustats[MAXUNITS]; int state; diff --git a/gst/units.c b/gst/units.c index aeced1b..8b84d52 100644 --- a/gst/units.c +++ b/gst/units.c @@ -181,6 +181,7 @@ int army_move_step (infos *info, army *ar, map *m, stats_unit *ustats) { int army_move (infos *info, army *ar, map *m, stats_unit *ustats) { for (int i=0; i<ar->uslen; i++) { ar->us[i].move_points += ustats[i].frame.speed; + if (ar->us[i].move_points > 1) ar->us[i].move_points = 1; } int iter = 0, finished = army_move_step(info, ar, m, ustats); for (; iter<5 && !finished; iter++) { @@ -197,6 +198,7 @@ int army_fire (infos *info, army *ar, map *m, a_dmg dmgs[], int lw = u->info.levels[LEVEL_CHASSIS]; for (int j=0; j<ustats[i].weaponlen; j++) { u->cooldown[j] += 1; + if (u->cooldown[j] > 1) u->cooldown[j] = 1; } } int dmgslen = 0; @@ -209,24 +211,26 @@ int army_fire (infos *info, army *ar, map *m, a_dmg dmgs[], for (int j=0; j<ustats[i].weaponlen; j++) { if (u->cooldown[j] <= 0) continue; float range = ustats[i].weapon[j].range; - unit_search(info, ar, m, u, t, range); - if (t[0]!=NULL) { - dmgs[dmgslen].u = u; - dmgs[dmgslen].t = t[0]; - - int t_i = 0; - for (int k=0; k<ar->uslen; k++) { - if (ar->us+k == t[0]) { t_i = k; break; } - } - float dam = stats_compute_damage( - &ustats[i].weapon[j], - &ustats[t_i].frame, u->reduced_armor); - - dmgs[dmgslen].dam = dam; - dmgslen++; - u->cooldown[j] -= ustats[i].weapon[j].cooldown; - u->charge -= ustats[i].weapon[j].charge_per_shot; - if (u->charge < 0) u->charge = 0; + while (u->cooldown[j] > 0) { + unit_search(info, ar, m, u, t, range); + if (t[0]!=NULL) { + dmgs[dmgslen].u = u; + dmgs[dmgslen].t = t[0]; + + int t_i = 0; + for (int k=0; k<ar->uslen; k++) { + if (ar->us+k == t[0]) { t_i = k; break; } + } + float dam = stats_compute_damage( + &ustats[i].weapon[j], + &ustats[t_i].frame, u->reduced_armor); + + dmgs[dmgslen].dam = dam; + dmgslen++; + u->cooldown[j] -= ustats[i].weapon[j].cooldown; + u->charge -= ustats[i].weapon[j].charge_per_shot; + if (u->charge < 0) u->charge = 0; + } else break; } } } @@ -715,13 +715,15 @@ void hud_process_overlay_game (graphic_settings *gs, hud *h, MKb *mkb, h->og.start_battle_flag = 1; } - // edit unit - int x = (int)((mkb->mx+gst->cam[0])/32); - int y = (int)((mkb->my+gst->cam[1])/32); - if (x >= 0 && y >= 0 && x < m->sx && y < m->sy) { - if (ar->grid[xytoi(m,x,y)] != NULL) { - hud_open_fnu(h, info, &ar->grid[xytoi(m,x,y)]->info, -2); - h->og.temp_place = -1; + if (SDL_GetModState() & KMOD_SHIFT) { + // edit unit + int x = (int)((mkb->mx+gst->cam[0])/32); + int y = (int)((mkb->my+gst->cam[1])/32); + if (x >= 0 && y >= 0 && x < m->sx && y < m->sy) { + if (ar->grid[xytoi(m,x,y)] != NULL) { + hud_open_fnu(h, info, &ar->grid[xytoi(m,x,y)]->info, -2); + h->og.temp_place = -1; + } } } } |