/** * @brief Starts the rendering engine. */ static void gl_fontRenderStart( const glFontStash* font, double x, double y, const glColour *c ) { double a; /* Enable textures. */ glEnable(GL_TEXTURE_2D); /* Set up matrix. */ gl_matrixMode(GL_MODELVIEW); gl_matrixPush(); gl_matrixTranslate( round(x), round(y) ); /* Handle colour. */ if (font_restoreLast) { a = (c==NULL) ? 1. : c->a; ACOLOUR(*font_lastCol,a); } else { if (c==NULL) glColor4d( 1., 1., 1., 1. ); else COLOUR(*c); } font_restoreLast = 0; /* Activate the appropriate VBOs. */ gl_vboActivateOffset( font->vbo_tex, GL_TEXTURE_COORD_ARRAY, 0, 2, GL_FLOAT, 0 ); gl_vboActivateOffset( font->vbo_vert, GL_VERTEX_ARRAY, 0, 2, GL_SHORT, 0 ); }
/** * @brief Renders a character. */ static int gl_fontRenderGlyph( glFontStash* stsh, uint32_t ch, const glColour *c, int state ) { GLushort ind[6]; double a; const glColour *col; int vbo_id; /* Handle escape sequences. */ if (ch == '\a') {/* Start sequence. */ return 1; } if (state == 1) { col = gl_fontGetColour( ch ); a = (c==NULL) ? 1. : c->a; if (col == NULL) { if (c==NULL) glColor4d( 1., 1., 1., 1. ); else COLOUR(*c); } else ACOLOUR(*col,a); font_lastCol = col; return 0; } /* Unicode goes here. * First try to find the glyph. */ glFontGlyph *glyph; glyph = gl_fontGetGlyph( stsh, ch ); if (glyph == NULL) { WARN(_("Unable to find glyph '%d'!"), ch ); return -1; } /* Activate texture. */ glBindTexture(GL_TEXTURE_2D, glyph->tex->id); /* VBO indices. */ vbo_id = glyph->vbo_id; ind[0] = vbo_id + 0; ind[1] = vbo_id + 1; ind[2] = vbo_id + 3; ind[3] = vbo_id + 1; ind[4] = vbo_id + 3; ind[5] = vbo_id + 2; /* Draw the element. */ glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, ind ); /* Translate matrix. */ gl_matrixTranslate( glyph->adv_x, glyph->adv_y ); return 0; }
/** * @brief Renders an individual weapon. * * @param w Weapon to render. * @param dt Current delta tick. */ static void weapon_render( Weapon* w, const double dt ) { double x,y, cx,cy, gx,gy; glTexture *gfx; double z; glColour c = { .r=1., .g=1., .b=1. }; switch (w->outfit->type) { /* Weapons that use sprites. */ case OUTFIT_TYPE_AMMO: case OUTFIT_TYPE_TURRET_AMMO: case OUTFIT_TYPE_BOLT: case OUTFIT_TYPE_TURRET_BOLT: gfx = outfit_gfx(w->outfit); /* Alpha based on strength. */ c.a = w->strength; /* Outfit spins around. */ if (outfit_isProp(w->outfit, OUTFIT_PROP_WEAP_SPIN)) { /* Check timer. */ w->anim -= dt; if (w->anim < 0.) { w->anim = outfit_spin(w->outfit); /* Increment sprite. */ w->sprite++; if (w->sprite >= gfx->sx*gfx->sy) w->sprite = 0; } /* Render. */ if (outfit_isBolt(w->outfit) && w->outfit->u.blt.gfx_end) gl_blitSpriteInterpolate( gfx, w->outfit->u.blt.gfx_end, w->timer / w->life, w->solid->pos.x, w->solid->pos.y, w->sprite % (int)gfx->sx, w->sprite / (int)gfx->sx, &c ); else gl_blitSprite( gfx, w->solid->pos.x, w->solid->pos.y, w->sprite % (int)gfx->sx, w->sprite / (int)gfx->sx, &c ); } /* Outfit faces direction. */ else { if (outfit_isBolt(w->outfit) && w->outfit->u.blt.gfx_end) gl_blitSpriteInterpolate( gfx, w->outfit->u.blt.gfx_end, w->timer / w->life, w->solid->pos.x, w->solid->pos.y, w->sx, w->sy, &c ); else gl_blitSprite( gfx, w->solid->pos.x, w->solid->pos.y, w->sx, w->sy, &c ); } break; /* Beam weapons. */ case OUTFIT_TYPE_BEAM: case OUTFIT_TYPE_TURRET_BEAM: gfx = outfit_gfx(w->outfit); /* Zoom. */ gl_cameraZoomGet( &z ); /* Position. */ gl_cameraGet( &cx, &cy ); gui_getOffset( &gx, &gy ); x = (w->solid->pos.x - cx)*z + gx; y = (w->solid->pos.y - cy)*z + gy; /* Set up the matrix. */ glMatrixMode(GL_PROJECTION); glPushMatrix(); glTranslated( x, y, 0. ); glRotated( 270. + w->solid->dir / M_PI * 180., 0., 0., 1. ); /* Preparatives. */ glEnable(GL_TEXTURE_2D); glBindTexture( GL_TEXTURE_2D, gfx->texture); glShadeModel(GL_SMOOTH); /* Actual rendering. */ glBegin(GL_QUAD_STRIP); /* Start faded. */ ACOLOUR(cWhite, 0.); glTexCoord2d( w->anim, 0. ); glVertex2d( -gfx->sh/2.*z, 0. ); glTexCoord2d( w->anim, 1. ); glVertex2d( +gfx->sh/2.*z, 0. ); /* Full strength. */ COLOUR(cWhite); glTexCoord2d( w->anim + 10. / gfx->sw, 0. ); glVertex2d( -gfx->sh/2.*z, 10.*z ); glTexCoord2d( w->anim + 10. / gfx->sw, 1. ); glVertex2d( +gfx->sh/2.*z, 10.*z ); glTexCoord2d( w->anim + 0.8*w->outfit->u.bem.range / gfx->sw, 0. ); glVertex2d( -gfx->sh/2.*z, 0.8*w->outfit->u.bem.range*z ); glTexCoord2d( w->anim + 0.8*w->outfit->u.bem.range / gfx->sw, 1. ); glVertex2d( +gfx->sh/2.*z, 0.8*w->outfit->u.bem.range*z ); /* Fades out. */ ACOLOUR(cWhite, 0.); glTexCoord2d( w->anim + w->outfit->u.bem.range / gfx->sw, 0. ); glVertex2d( -gfx->sh/2.*z, w->outfit->u.bem.range*z ); glTexCoord2d( w->anim + w->outfit->u.bem.range / gfx->sw, 1. ); glVertex2d( +gfx->sh/2.*z, w->outfit->u.bem.range*z ); glEnd(); /* GL_QUAD_STRIP */ /* Do the beam movement. */ w->anim -= 5. * dt; if (w->anim <= -gfx->sw) w->anim += gfx->sw; /* Clean up. */ glDisable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glPopMatrix(); /* GL_PROJECTION */ gl_checkErr(); break; default: WARN("Weapon of type '%s' has no render implemented yet!", w->outfit->name); break; } } /** * @brief Checks to see if the weapon can hit the pilot. * * @param w Weapon to check if hits pilot. * @param p Pilot to check if is hit by weapon. * @return 1 if can be hit, 0 if can't. */ static int weapon_checkCanHit( Weapon* w, Pilot *p ) { Pilot *parent; /* Can't hit invincible stuff. */ if (pilot_isFlag(p, PILOT_INVINCIBLE)) return 0; /* Can never hit same faction. */ if (p->faction == w->faction) return 0; /* Go "through" dead pilots. */ if (pilot_isFlag(p, PILOT_DEAD)) return 0; /* Player behaves differently. */ if (w->faction == FACTION_PLAYER) { /* Always hit without safety. */ if (!weapon_safety) return 1; /* Always hit target. */ else if (w->target == p->id) return 1; /* Always hit hostiles. */ else if (pilot_isFlag(p, PILOT_HOSTILE)) return 1; /* Always hit unbribed enemies. */ else if (!pilot_isFlag(p, PILOT_BRIBED) && areEnemies(w->faction, p->faction)) return 1; /* Miss rest - can be neutral/ally. */ else return 0; } /* Let hostiles hit player. */ if (p->faction == FACTION_PLAYER) { parent = pilot_get(w->parent); if (parent != NULL) { if (pilot_isFlag(parent, PILOT_BRIBED)) return 0; if (pilot_isFlag(parent, PILOT_HOSTILE)) return 1; } } /* Hit non-allies. */ if (areEnemies(w->faction, p->faction)) return 1; return 0; }
/** * @brief Renders the custom map widget. * * @param bx Base X position to render at. * @param by Base Y position to render at. * @param w Width of the widget. * @param h Height of the widget. */ static void map_render( double bx, double by, double w, double h ) { int i,j, n,m; double x,y,r, tx,ty; StarSystem *sys, *jsys, *hsys; glColour* col; r = 5.; x = (bx - map_xpos + w/2) * 1.; y = (by - map_ypos + h/2) * 1.; /* background */ COLOUR(cBlack); glBegin(GL_QUADS); glVertex2d( bx, by ); glVertex2d( bx, by+h ); glVertex2d( bx+w, by+h ); glVertex2d( bx+w, by ); glEnd(); /* GL_QUADS */ /* render the star systems */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* check to make sure system is known or adjacent to known (or marked) */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED) && !space_sysReachable(sys)) continue; /* system colours */ if (sys==cur_system) col = &cRadar_tPlanet; else if (!sys_isKnown(sys) || (sys->nplanets==0)) col = &cInert; else col = faction_getColour( sys->faction); COLOUR(*col); /* draw the system */ tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; gl_drawCircleInRect( tx, ty, r, bx, by, w, h ); /* draw the system name */ if (sys_isKnown(sys) && (map_zoom > 0.5 )) { tx = x + 7. + sys->pos.x * map_zoom; ty = y - 5. + sys->pos.y * map_zoom; gl_print( &gl_smallFont, tx + SCREEN_W/2., ty + SCREEN_H/2., &cWhite, sys->name ); } if (!sys_isKnown(sys)) continue; /* we don't draw hyperspace lines */ /* draw the hyperspace paths */ glShadeModel(GL_SMOOTH); /* cheaply use transparency instead of actually calculating * from where to where the line must go :) */ for (j=0; j<sys->njumps; j++) { jsys = system_getIndex( sys->jumps[j] ); if (hyperspace_target != -1) hsys = system_getIndex( cur_system->jumps[hyperspace_target] ); n = map_inPath(jsys); m = map_inPath(sys); /* set the colours */ /* is the route the current one? */ if ((hyperspace_target != -1) && ( ((cur_system==sys) && (j==hyperspace_target)) || ((cur_system==jsys) && (sys==hsys )))) { if (player->fuel < HYPERSPACE_FUEL) col = &cRed; else col = &cGreen; } /* is the route part of the path? */ else if ((n > 0) && (m > 0)) { if ((n == 2) || (m == 2)) /* out of fuel */ col = &cRed; else col = &cYellow; } else col = &cDarkBlue; glBegin(GL_LINE_STRIP); ACOLOUR(*col,0.); tx = x + sys->pos.x * map_zoom; ty = y + sys->pos.y * map_zoom; glVertex2d( tx, ty ); COLOUR(*col); tx += (jsys->pos.x - sys->pos.x)/2. * map_zoom; ty += (jsys->pos.y - sys->pos.y)/2. * map_zoom; glVertex2d( tx, ty ); ACOLOUR(*col,0.); tx = x + jsys->pos.x * map_zoom; ty = y + jsys->pos.y * map_zoom; glVertex2d( tx, ty ); glEnd(); /* GL_LINE_STRIP */ } glShadeModel(GL_FLAT); } /* Second pass to put markers. */ for (i=0; i<systems_nstack; i++) { sys = system_getIndex( i ); /* We only care about marked now. */ if (!sys_isFlag(sys, SYSTEM_MARKED | SYSTEM_CMARKED)) continue; /* Get the position. */ tx = x + sys->pos.x*map_zoom; ty = y + sys->pos.y*map_zoom; /* Count markers. */ n = (sys_isFlag(sys, SYSTEM_CMARKED)) ? 1 : 0; n += sys->markers_misc; n += sys->markers_cargo; n += sys->markers_rush; /* Draw the markers. */ j = 0; if (sys_isFlag(sys, SYSTEM_CMARKED)) { map_drawMarker( tx, ty, r, n, j, 0 ); j++; } for (m=0; m<sys->markers_misc; m++) { map_drawMarker( tx, ty, r, n, j, 1 ); j++; } for (m=0; m<sys->markers_rush; m++) { map_drawMarker( tx, ty, r, n, j, 2 ); j++; } for (m=0; m<sys->markers_cargo; m++) { map_drawMarker( tx, ty, r, n, j, 3 ); j++; } } /* selected planet */ if (map_selected != -1) { sys = system_getIndex( map_selected ); COLOUR(cRed); gl_drawCircleInRect( x + sys->pos.x * map_zoom, y + sys->pos.y * map_zoom, r+3., bx, by, w, h ); } }