[Add] Per pixel collision.
[Fix] Fleets now start at random location. -- Still needs improvement.
This commit is contained in:
parent
28c5b6ea73
commit
acf4150079
@ -11,9 +11,9 @@ function attack()
|
||||
target = 0
|
||||
dir = face(target)
|
||||
dist = getdist(getpos(target))
|
||||
if dir < 10 and dist > 100 then
|
||||
if dir < 10 and dist > 300 then
|
||||
accel()
|
||||
elseif dir < 10 and dist < 100 then
|
||||
elseif dir < 10 and dist < 300 then
|
||||
shoot()
|
||||
end
|
||||
end
|
||||
|
6
src/ai.c
6
src/ai.c
@ -164,7 +164,11 @@ void ai_exit(void) {
|
||||
// Heart of hearts of the ai!! Brains of the pilot.
|
||||
void ai_think(Pilot* pilot) {
|
||||
cur_pilot = pilot; // Set current pilot being processed.
|
||||
pilot_acc = pilot_turn = 0.; // Clean up some variables.
|
||||
|
||||
// Clean up some variables.
|
||||
pilot_acc = pilot_turn = 0.;
|
||||
//pilot_primary = 0;
|
||||
|
||||
if(cur_pilot->task == NULL)
|
||||
// Idle git!
|
||||
AI_LCALL("control");
|
||||
|
50
src/collision.c
Normal file
50
src/collision.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include "main.h"
|
||||
#include "log.h"
|
||||
#include "collision.h"
|
||||
|
||||
// Collide sprite at (asx, asy) int 'at' at pos 'ap' with sprite at (bsx,bsy) in 'bt' at 'bp'
|
||||
// at - Texture a.
|
||||
// asx - Position of x of sprite a.
|
||||
// asy - Position of y of sprite a.
|
||||
// ap - Position in space of sprite a.
|
||||
// bt - Texture b.
|
||||
// bsx - Position of x of sprite b.
|
||||
// bsy - Position of y of sprite b.
|
||||
// bp - Position in space of sprite b.
|
||||
int CollideSprite(const gl_texture* at, const int asx, const int asy, const Vec2* ap,
|
||||
const gl_texture* bt, const int bsx, const int bsy, const Vec2* bp) {
|
||||
|
||||
int x,y;
|
||||
|
||||
// a - cube coords.
|
||||
int ax1 = (int)VX(*ap) - (int)(at->sw)/2;
|
||||
int ay1 = (int)VY(*ap) - (int)(at->sh)/2;
|
||||
int ax2 = ax1 + (int)(at->sw) - 1;
|
||||
int ay2 = ay1 + (int)(at->sh) - 1;
|
||||
|
||||
// b - cube coords.
|
||||
int bx1 = (int)VX(*bp) - (int)(bt->sw)/2;
|
||||
int by1 = (int)VY(*bp) - (int)(bt->sh)/2;
|
||||
int bx2 = bx1 + (int)(bt->sw) - 1;
|
||||
int by2 = by1 + (int)(bt->sh) - 1;
|
||||
|
||||
// Check if bounding boxes intersect.
|
||||
if((bx2 < ax1) || (ax2 < bx1)) return 0;
|
||||
if((by2 < ay1) || (ay2 < by1)) return 0;
|
||||
|
||||
// Define the remaining binding box.
|
||||
int inter_x0 = MAX(ax1, bx1);
|
||||
int inter_x1 = MIN(ax2, bx2);
|
||||
int inter_y0 = MAX(ay1, by1);
|
||||
int inter_y1 = MIN(ay2, by2);
|
||||
|
||||
for(y = inter_y0; y <= inter_y1; y++)
|
||||
for(x = inter_x0; x <= inter_x1; x++)
|
||||
// Computer offsets for surface before passing to TransparentPixel test.
|
||||
if((!gl_isTrans(at, asx*(int)(at->sw) + x-ax1, asy*(int)(at->sh) + y-ay1)) &&
|
||||
(!gl_isTrans(bt, bsx*(int)(bt->sw) + x-bx1, bsy*(int)(bt->sh) + y-by1)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
7
src/collision.h
Normal file
7
src/collision.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "opengl.h"
|
||||
#include "physics.h"
|
||||
|
||||
int CollideSprite(const gl_texture* at, const int asx, const int asy, const Vec2* ap,
|
||||
const gl_texture* bt, const int bsx, const int bsy, const Vec2* bp);
|
||||
|
83
src/opengl.c
83
src/opengl.c
@ -32,6 +32,8 @@ gl_font gl_defFont;
|
||||
|
||||
// Misc.
|
||||
static int SDL_VFlipSurface(SDL_Surface* surface);
|
||||
static int SDL_IsTrans(SDL_Surface* s, int x, int y);
|
||||
static uint8_t* SDL_MapTrans(SDL_Surface* s);
|
||||
static int pot(int n);
|
||||
// gl_texture.
|
||||
static GLuint gl_loadSurface(SDL_Surface* surface, int* rw, int* rh);
|
||||
@ -76,6 +78,57 @@ static int SDL_VFlipSurface(SDL_Surface* surface) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return true if position (x,y) of s is transparent.
|
||||
static int SDL_IsTrans(SDL_Surface* s, int x, int y) {
|
||||
int bpp = s->format->BytesPerPixel;
|
||||
// p is the address to the pixel we want to retrieve.
|
||||
Uint8* p = (Uint8*)s->pixels + y * s->pitch + x*bpp;
|
||||
|
||||
Uint32 pixelcolor = 0;
|
||||
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
pixelcolor = *p;
|
||||
break;
|
||||
case 2:
|
||||
pixelcolor = *(Uint16*)p;
|
||||
break;
|
||||
case 3:
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
||||
pixelcolor = p[0] << 16 | p[1] << 8 | p[2];
|
||||
else
|
||||
pixelcolor = p[0] | p[1] << 8 | p[2] << 16;
|
||||
break;
|
||||
case 4:
|
||||
pixelcolor = *(Uint32*)p;
|
||||
break;
|
||||
}
|
||||
// Test whetehr the pixels color is equal to color of
|
||||
//transparent pixels for that surface.
|
||||
return (pixelcolor == s->format->colorkey);
|
||||
}
|
||||
|
||||
// Map the surface transparancy.
|
||||
// Return 0 on success.
|
||||
static uint8_t* SDL_MapTrans(SDL_Surface* s) {
|
||||
// Allocate memory for just enough bits to hold all the data we need.
|
||||
int size = s->w*s->h/8 + ((s->w*s->h%8)?1:0);
|
||||
uint8_t* t = malloc(size);
|
||||
bzero(t, size); // *must* be set to zero.
|
||||
|
||||
if(t == NULL) {
|
||||
WARN("Out of memeory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int i, j;
|
||||
for(i = 0; i < s->h; i++)
|
||||
for(j = 0; j < s->w; j++) // Set each bit to be 1 if not transparent or 0 if it is.
|
||||
t[(i*s->w+j)/8] |= (SDL_IsTrans(s,j,i)) ? 0 : (1<<((i*s->w+j)%8));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
// ================
|
||||
// TEXTURE!
|
||||
// ================
|
||||
@ -187,12 +240,16 @@ gl_texture* gl_loadImage(SDL_Surface* surface) {
|
||||
texture->sw = texture->w;
|
||||
texture->sh = texture->h;
|
||||
|
||||
texture->trans = NULL;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
// Load the image directly as an opengl texture.
|
||||
gl_texture* gl_newImage(const char* path) {
|
||||
SDL_Surface* tmp, *surface;
|
||||
gl_texture* t;
|
||||
void* trans = NULL;
|
||||
uint32_t filesize;
|
||||
char* buf = pack_readfile(DATA, (char*)path, &filesize);
|
||||
if(buf == NULL) {
|
||||
@ -216,11 +273,18 @@ gl_texture* gl_newImage(const char* path) {
|
||||
|
||||
SDL_FreeSurface(tmp); // Free the temp surface.
|
||||
|
||||
SDL_LockSurface(surface);
|
||||
trans = SDL_MapTrans(surface);
|
||||
SDL_UnlockSurface(surface);
|
||||
|
||||
if(SDL_VFlipSurface(surface)) {
|
||||
WARN("Error flipping surface");
|
||||
return NULL;
|
||||
}
|
||||
return gl_loadImage(surface);
|
||||
t = gl_loadImage(surface);
|
||||
t->trans = trans;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
// Load the texture immediately, but also set is as a sprite.
|
||||
@ -238,9 +302,26 @@ gl_texture* gl_newSprite(const char* path, const int sx, const int sy) {
|
||||
// Free the texture.
|
||||
void gl_freeTexture(gl_texture* texture) {
|
||||
glDeleteTextures(1, &texture->texture);
|
||||
if(texture->trans) free(texture->trans);
|
||||
free(texture);
|
||||
}
|
||||
|
||||
// Return true if pixel at pos (x,y) is transparent.
|
||||
int gl_isTrans(const gl_texture* t, const int x, const int y) {
|
||||
return !(t->trans[(y*(int)(t->w)+x)/8] & (1<<((y*(int)(t->w)+x)%8)));
|
||||
}
|
||||
|
||||
// Set x and y to be the appropriate sprite for gl_texture using dir.
|
||||
void gl_getSpriteFromDir(int* x, int* y, const gl_texture* t, const double dir) {
|
||||
int s = (int)(dir / (2.0*M_PI / (t->sy*t->sx)));
|
||||
|
||||
// Make sure the sprite is "in range".
|
||||
if(s > (int)(t->sy*t->sx)-1) s = s % (int)(t->sy*t->sx);
|
||||
|
||||
*x = s % (int)t->sx;
|
||||
*y = s / (int)t->sy;
|
||||
}
|
||||
|
||||
// ================
|
||||
// BLITTING!
|
||||
// ================
|
||||
|
@ -35,6 +35,7 @@ typedef struct {
|
||||
double sx, sy; // Number of sprites on x and y axes.
|
||||
double sw, sh; // Size of each sprite.
|
||||
GLuint texture; // The opengl texture itself.
|
||||
uint8_t* trans; // Maps the transparency.
|
||||
} gl_texture;
|
||||
|
||||
// Font info.
|
||||
@ -66,3 +67,7 @@ void gl_print(const gl_font* ft_font, const Vec2* pos, const char* fmt, ...);
|
||||
int gl_init(void);
|
||||
void gl_exit(void);
|
||||
|
||||
// Misc.
|
||||
int gl_isTrans(const gl_texture* t, const int x, const int y);
|
||||
void gl_getSpriteFromDir(int* x, int* y, const gl_texture* t, const double dir);
|
||||
|
||||
|
@ -57,6 +57,13 @@ double vect_angle(const Vec2* ref, const Vec2* v) {
|
||||
return ANGLE(VX(*v)-VX(*ref), VY(*v)-VY(*ref));
|
||||
}
|
||||
|
||||
void vect_cadd(Vec2* v, const double x, const double y) {
|
||||
v->x -= x;
|
||||
v->y -= y;
|
||||
v->mod = MOD(v->x, v->y);
|
||||
v->angle = ANGLE(v->x, v->y);
|
||||
}
|
||||
|
||||
|
||||
// ================
|
||||
// SOLID!
|
||||
|
@ -28,6 +28,7 @@ void vect_pset(Vec2* v, const double mod, const double angle);
|
||||
void vectcpy(Vec2* dest, const Vec2* src);
|
||||
void vectnull(Vec2* v);
|
||||
double vect_angle(const Vec2* ref, const Vec2* v);
|
||||
void vect_cadd(Vec2* v, const double x, const double y);
|
||||
|
||||
// Describe any solid in 2D space.
|
||||
struct Solid {
|
||||
|
10
src/pilot.c
10
src/pilot.c
@ -120,16 +120,12 @@ void pilot_hit(Pilot* p, const double damage_shield, const double damage_armor)
|
||||
|
||||
// Render the pilot.
|
||||
void pilot_render(Pilot* p) {
|
||||
int sprite;
|
||||
gl_texture* t = p->ship->gfx_space;
|
||||
int sx, sy;
|
||||
|
||||
// Get the sprite corresponding to the direction facing.
|
||||
sprite = (int)(p->solid->dir / (2.0*M_PI / (t->sy * t->sx)));
|
||||
gl_getSpriteFromDir(&sx, &sy, p->ship->gfx_space, p->solid->dir);
|
||||
|
||||
// Ugly hack to make sure it's always "inbound".
|
||||
if(sprite > (int)(t->sy*t->sx)-1) sprite = (int)(t->sy*t->sx)-1;
|
||||
|
||||
gl_blitSprite(t, &p->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy);
|
||||
gl_blitSprite(p->ship->gfx_space, &p->solid->pos, sx, sy);
|
||||
}
|
||||
|
||||
// Update the pilot.
|
||||
|
15
src/space.c
15
src/space.c
@ -196,6 +196,8 @@ static PlanetClass planetclass_get(const char a) {
|
||||
// Init the system.
|
||||
void space_init(const char* sysname) {
|
||||
int i, j;
|
||||
Vec2 v, vn;
|
||||
|
||||
for(i = 0; i < nsystems; i++)
|
||||
if(strcmp(sysname, systems[i].name)==0)
|
||||
break;
|
||||
@ -211,17 +213,22 @@ void space_init(const char* sysname) {
|
||||
stars[i].y = (double)RNG(-STAR_BUF, gl_screen.h + STAR_BUF);
|
||||
}
|
||||
// Set up fleets -> pilots.
|
||||
vectnull(&vn);
|
||||
for(i = 0; i < cur_system->nfleets; i++)
|
||||
if(RNG(0,100) <= cur_system->fleets[i].chance) // Check fleet.
|
||||
if(RNG(0,100) <= cur_system->fleets[i].chance) {// Check fleet.
|
||||
vect_pset(&v, 2*RNG(MIN_HYPERSPACE_DIST/2, MIN_HYPERSPACE_DIST), RNG(0, 360)*M_PI/180.);
|
||||
for(j = 0; j < cur_system->fleets[i].fleet->npilots; j++)
|
||||
if(RNG(0,100) <= cur_system->fleets[i].fleet->pilots[j].chance)
|
||||
if(RNG(0,100) <= cur_system->fleets[i].fleet->pilots[j].chance) {
|
||||
vect_cadd(&v, RNG(-50, 50), RNG(-50, 50));
|
||||
pilot_create(cur_system->fleets[i].fleet->pilots[j].ship,
|
||||
cur_system->fleets[i].fleet->pilots[j].name,
|
||||
cur_system->fleets[i].fleet->faction,
|
||||
RNG(0,360),
|
||||
NULL,
|
||||
vect_angle(&v,&vn),
|
||||
&v,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the planets of name 'name'.
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define MIN_HYPERSPACE_DIST 1500
|
||||
|
||||
// Load/Exit.
|
||||
void space_init(const char* sysname);
|
||||
int space_load(void);
|
||||
|
19
src/weapon.c
19
src/weapon.c
@ -8,6 +8,7 @@
|
||||
#include "log.h"
|
||||
#include "rng.h"
|
||||
#include "pilot.h"
|
||||
#include "collision.h"
|
||||
#include "weapon.h"
|
||||
|
||||
// Some stuff from pilot.
|
||||
@ -102,23 +103,27 @@ void weapons_update(const double dt, WeaponLayer layer) {
|
||||
|
||||
// Render the weapons.
|
||||
static void weapon_render(const Weapon* w) {
|
||||
int sprite;
|
||||
gl_texture* t = w->outfit->gfx_space;
|
||||
int sx, sy;
|
||||
|
||||
// Get the sprite corresponding to the direction facing.
|
||||
sprite = (int)(w->solid->dir / (2.0*M_PI / (t->sy*t->sx)));
|
||||
gl_getSpriteFromDir(&sx, &sy, w->outfit->gfx_space, w->solid->dir);
|
||||
|
||||
gl_blitSprite(t, &w->solid->pos, sprite % (int)t->sx, sprite / (int)t->sy);
|
||||
gl_blitSprite(w->outfit->gfx_space, &w->solid->pos, sx, sy);
|
||||
}
|
||||
|
||||
// Update the weapon.
|
||||
static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
|
||||
int i;
|
||||
int i, wsx, wsy, psx, psy;
|
||||
gl_getSpriteFromDir(&wsx, &wsy, w->outfit->gfx_space, w->solid->dir);
|
||||
|
||||
for(i = 0; i < pilots; i++) {
|
||||
gl_getSpriteFromDir(&psx, &psy, pilot_stack[i]->ship->gfx_space,
|
||||
pilot_stack[i]->solid->dir);
|
||||
|
||||
if((w->parent != pilot_stack[i]->id) && // The pilot hasn't shoot it.
|
||||
!areAllies(pilot_get(w->parent)->faction, pilot_stack[i]->faction) &&
|
||||
(DIST(w->solid->pos, pilot_stack[i]->solid->pos) < (PILOT_SIZE_APROX *
|
||||
w->outfit->gfx_space->sw/2. + pilot_stack[i]->ship->gfx_space->sw/2.))) {
|
||||
CollideSprite(w->outfit->gfx_space, wsx, wsy, &w->solid->pos,
|
||||
pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos)) {
|
||||
pilot_hit(pilot_stack[i], w->outfit->damage_shield, w->outfit->damage_armor);
|
||||
weapon_destroy(w, layer);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user