wolf3d-ios/wolf3d/newCode/iphone/iphone_menus.c

1061 lines
26 KiB
C

/*
Copyright (C) 2009 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "../wolfiphone.h"
int intermissionStartFrameNum;
int hasReleased;
menuState_t menuState;
colour4_t highlightColor = { 128, 128, 128, 255 };
colour4_t colorPressed = { 128, 128, 0, 255 };
/*
==================
iphoneDrawPic
==================
*/
void iphoneDrawPic( int x, int y, int w, int h, const char *pic ) {
R_Draw_StretchPic( x, y, w, h, pic );
}
/*
==================
iphoneDrawPicWithTouch
==================
*/
int iphoneDrawPicWithTouch( int x, int y, int w, int h, const char *pic ) {
int r = TouchReleased( x, y, w, h );
if ( r ) {
// make sure it is full intensity if it is touch-released, even if
// it wasn't active previously
pfglColor3f( 1, 1, 1 );
}
R_Draw_StretchPic( x, y, w, h, pic );
if ( TouchDown( x, y, w, h ) ) {
colour4_t color = { 255, 255, 255, 64 };
R_Draw_Blend( x, y, w, h, color );
}
return r;
}
/*
==================
iphoneSlider
==================
*/
void iphoneSlider( int x, int y, int w, int h, const char *title, cvar_t *cvar,
float min, float max ) {
float value = cvar->value;
char str[80];
float f = ( value - min ) / ( max - min );
colour4_t backColor = { 32, 32, 80, 255 };
colour4_t highlightColor = { 64, 64, 160, 255 };
if ( f < 0 ) {
f = 0;
}
if ( f > 1 ) {
f = 1;
}
// draw the background
R_Draw_Fill( x, y, w, h, backColor );
// draw the current range
R_Draw_Fill( x+2, y+2, f*(w-4), h-4, highlightColor );
// draw the title and fraction
sprintf( str, "%s : %i%%", title, (int)(f*100) );
iphoneCenterText( x+ w/2, y+h/2-8, str );
// check for touches
if ( numTouches > 0 && touches[0][0] >= x && touches[0][0] < x + w
&& touches[0][1] >= y && touches[0][1] < y+ h ) {
float newValue;
float delta;
f = (float)( touches[0][0] - x ) / w;
// round to tenths
f = (int)( ( f + 0.05 ) * 10 ) * 0.1f;
if ( f < 0 ) {
f = 0;
}
if ( f > 1.0 ) {
f = 1.0;
}
newValue = min + f * ( max - min );
delta = fabs( newValue - cvar->value );
if ( f == 0 && cvar->value == 0 ) {
// special case of disable-at-0
} else if ( delta > 0.01 ) {
Cvar_SetValue( cvar->name, newValue );
Sound_StartLocalSound( "iphone/slide_01.wav" );
}
}
}
/*
==================
BackButton
==================
*/
int BackButton() {
if ( iphoneDrawPicWithTouch( 0, 0, 64, 32, "iphone/button_back.tga" ) ) {
return 1;
}
return 0;
}
void GetMoreLevels( int x, int y ) {
if ( iphoneDrawPicWithTouch( x, y, 128, 64, "iphone/button_levels.tga" ) ) {
// directly to the app store for more levels
OpenURL( "http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=304694876" );
}
}
/*
==================
SaveTheGame
==================
*/
extern W8 areaconnect[ NUMAREAS ][ NUMAREAS ];
extern _boolean areabyplayer[ NUMAREAS ];
void SaveTheGame() {
FILE *f;
char path[1024];
int version = SAVEGAME_VERSION;
int i;
my_snprintf( path, sizeof( path ), "%s/savegame.bin", iphoneDocDirectory );
f = fopen( path, "wb" );
if( ! f ) {
Com_Printf( "Could not open savegame.bin.\n" );
return;
}
// turn the r_world->Doors.doors from pointers to indexes
// ok to be destructive, because we are quiting
for ( i = 0 ; i < r_world->Doors.doornum ; i++ ) {
int index = r_world->Doors.Doors[i] - &r_world->Doors.DoorMap[0][0];
assert( index >= 0 && index < 4096 );
r_world->Doors.Doors[i] = (void *)index;
}
// this is only used for the mutant death face, so just
// clear it instead of fixing it up
Player.LastAttacker = NULL;
currentMap.version = SAVEGAME_VERSION;
fwrite( &currentMap, 1,sizeof(currentMap), f );
fwrite( r_world, 1,sizeof(*r_world), f );
fwrite( &LevelRatios, 1,sizeof(LevelRatios), f );
fwrite( &levelstate, 1,sizeof(levelstate), f );
fwrite( Guards, 1,sizeof(Guards), f );
fwrite( areaconnect, 1,sizeof(areaconnect), f );
fwrite( areabyplayer, 1,sizeof(areabyplayer), f );
fwrite( &PWall, 1,sizeof(PWall), f );
fwrite( &Player, 1,sizeof(Player), f );
fwrite( &version, 1,sizeof(version), f );
fclose( f );
}
/*
==================
LoadTheGame
==================
*/
int LoadTheGame() {
FILE *f;
char path[1024];
int version;
int i;
int oldCompleted;
my_snprintf( path, sizeof( path ), "%s/savegame.bin", iphoneDocDirectory );
f = fopen( path, "rb" );
if( ! f ) {
Com_Printf( "Could not open savegame.bin.\n" );
return 0;
}
fread( &currentMap, 1,sizeof(currentMap) , f);
if ( currentMap.version != SAVEGAME_VERSION ) {
Com_Printf( "Savegame header version mismatch: %i != %i\n", currentMap.version, SAVEGAME_VERSION );
fclose( f );
return 0;
}
// do a normal map start
Cvar_SetValue( skill->name, currentMap.skill );
PL_NewGame( &Player );
oldCompleted = currentMap.levelCompleted;
iphoneStartMap( currentMap.episode, currentMap.map, currentMap.skill );
currentMap.levelCompleted = oldCompleted;
// load modifiactions on top
r_world = Z_Malloc( sizeof( *r_world ) );
fread( r_world, 1,sizeof(*r_world), f);
fread( &LevelRatios, 1,sizeof(LRstruct), f );
fread( &levelstate, 1,sizeof(levelstate), f );
fread( Guards, 1,sizeof(Guards), f );
fread( areaconnect, 1,sizeof(areaconnect), f );
fread( areabyplayer, 1,sizeof(areabyplayer), f );
fread( &PWall, 1,sizeof(PWall), f );
fread( &Player, 1,sizeof(Player), f );
fread( &version, 1,sizeof(version), f );
fclose( f );
if ( version != SAVEGAME_VERSION ) {
Com_Printf( "Savegame trailer version mismatch: %i != %i\n", version, SAVEGAME_VERSION );
return 0;
}
// turn the r_world->Doors.doors back to pointers
for ( i = 0 ; i < r_world->Doors.doornum ; i++ ) {
int index = (int)r_world->Doors.Doors[i];
assert( index >= 0 && index < 4096 );
r_world->Doors.Doors[i] = &r_world->Doors.DoorMap[0][0] + index;
}
return 1;
}
/*
==================
iphoneStartMap
This does not reset the player, so call PL_NewGame( &Player ) if it is a new start.
==================
*/
void iphoneStartMap( int episodeNum, int mapNum, int skillLevel ) {
char command[128];
int levelNum = episodeNum*10+mapNum;
Com_Printf( "iphoneStartMap( %i, %i, %i )\n", episodeNum, mapNum, skillLevel );
// get the sound playing
Sound_Update( vnull, vnull, vnull, vnull );
// clean up game feedback
damageflash = 0;
bonusFrameNum = 0;
attackDirTime[0] = 0;
attackDirTime[1] = 0;
// note that this has been tried now
currentMap.mapFlags[currentMap.skill][levelNum] |= MF_TRIED;
// start the game
currentMap.episode = episodeNum;
currentMap.map = mapNum;
currentMap.skill = skillLevel;
currentMap.levelCompleted = 0;
Cvar_SetValue( skill->name, skillLevel );
Cvar_SetValue( episode->name, episodeNum );
sprintf( command, "w%i%i", currentMap.episode, currentMap.map );
Client_PrepRefresh( command );
menuState = IPM_GAME;
}
/*
==================
iphoneMainMenu
==================
*/
void iphoneMainMenu() {
char str[80];
float scale = 40 / 32.0;
iphoneDrawPic( 480-256, 0, 256, 128, "iphone/wolf_logo.tga" );
#ifdef EPISODE1
iphoneDrawPic( -20, 0, 256, 64, "iphone/ep_1.tga" );
GetMoreLevels( 0, 96 );
#else
iphoneDrawPic( -20, 0, 256, 64, "iphone/ep_1_6.tga" );
#endif
iphoneDrawPic( 0, 320 - 128, 128, 128, "iphone/id_logo.tga" );
if ( iphoneDrawPicWithTouch( 300 - 64*scale, 80, 128*scale, 64*scale, "iphone/button_resume.tga" ) ) {
// if the game was saved at the intermission screen, immediately
// bring it back up when it is loaded
if ( currentMap.levelCompleted ) {
iphoneStartIntermission( 0 );
} else {
menuState = IPM_GAME;
}
}
sprintf( str, "E%iM%i", currentMap.episode+1, currentMap.map+1 );
iphoneCenterText( 300, 80+34*scale, str );
if ( iphoneDrawPicWithTouch( 300 - 64*scale, 170, 128*scale, 32*scale, "iphone/button_control.tga" ) ) {
menuState = IPM_CONTROLS;
}
if ( iphoneDrawPicWithTouch( 300 - 64*scale, 220, 128*scale, 32*scale, "iphone/button_new.tga" ) ) {
menuState = IPM_SKILL;
}
if ( iphoneDrawPicWithTouch( 300 - 64*scale, 270, 128*scale, 32*scale, "iphone/button_web.tga" ) ) {
OpenURL( "http://www.idsoftware.com/wolfenstein3dclassic/" );
}
}
/*
==================
iphoneControlMenu
==================
*/
void iphoneControlMenu() {
int i;
if ( BackButton() ) {
menuState = IPM_MAIN;
}
for ( i = 0 ; i < 4 ; i++ ) {
char str[128];
int remap[4] = { 3,4,1,2}; // artist named them differently than intended...
sprintf( str, "iphone/layout_%i.tga", remap[i] );
if ( i != controlScheme->value ) {
pfglColor3f( 0.5, 0.5, 0.5 );
}
if ( iphoneDrawPicWithTouch( 120 * i, 40, 120, 120, str ) ) {
Cvar_SetValue( controlScheme->name, i );
}
pfglColor3f( 1, 1, 1 );
}
iphoneSlider( 20, 170, 440, 40, "sensitivity", sensitivity, 0, 1 );
iphoneSlider( 20, 220, 440, 40, "tilt move speed", tiltMove, 5000, 30000 );
if ( tiltMove->value == 5000 ) {
Cvar_SetValue( tiltMove->name, 0 );
}
if ( tiltMove->value ) {
Cvar_SetValue( tiltTurn->name, 0 );
}
iphoneSlider( 20, 270, 440, 40, "tilt turn speed", tiltTurn, 500, 3000 );
if ( tiltTurn->value == 500 ) {
Cvar_SetValue( tiltTurn->name, 0 );
}
if ( tiltTurn->value ) {
Cvar_SetValue( tiltMove->name, 0 );
}
//iphoneSlider( 20, 280, 440, 40, "tilt fire", tiltFire, 0, 1 );
}
/*
==================
iphoneSkillMenu
==================
*/
void iphoneSkillMenu() {
int s;
char str[64];
if ( BackButton() ) {
menuState = IPM_MAIN;
}
// highlight the current skill selection
s = (int)skill->value;
// R_Draw_Fill( 80, 40+64*s, 320, 64, highlightColor );
for ( s = 0 ; s < 4 ; s++ ) {
my_snprintf( str, sizeof( str ), "iphone/button_skill%i.tga", s+1 );
if ( s != (int)skill->value ) {
pfglColor3f( 0.5, 0.5, 0.5 );
}
if ( iphoneDrawPicWithTouch( 112, 40+64*s, 256, 64, str ) ) {
Cvar_SetValue( skill->name, s );
menuState = IPM_EPISODE;
}
pfglColor3f( 1, 1, 1 );
}
}
/*
==================
iphoneEpisodeMenu
==================
*/
void iphoneEpisodeMenu() {
int e;
char str[64];
#ifdef EPISODE1
int numE = 1;
#else
int numE = 6;
#endif
if ( BackButton() ) {
menuState = IPM_SKILL;
}
// 96 x 48 images
for ( e = 0 ; e < numE ; e++ ) {
my_snprintf( str, sizeof( str ), "iphone/button_ep%i.tga", e+1 );
if ( e != (int)episode->value ) {
pfglColor3f( 0.5, 0.5, 0.5 );
}
if ( iphoneDrawPicWithTouch( 48, 32+48*e, 384, 48, str ) ) {
Cvar_SetValue( episode->name, e );
menuState = IPM_MAPS;
}
pfglColor3f( 1, 1, 1 );
}
#ifdef EPISODE1
// buy more episodes button
GetMoreLevels( 240 - 64, 200 );
#endif
}
/*
==================
iphoneMapMenu
==================
*/
void iphoneMapMenu() {
int e, m, s;
char str[64];
if ( BackButton() ) {
menuState = IPM_EPISODE;
}
// draw the level selection
e = episode->value;
if ( e < 0 ) {
e = 0;
}
if ( e > 5 ) {
e = 5;
}
s = skill->value;
if ( s < 0 ) {
s = 0;
}
if ( s > 3 ) {
s = 3;
}
// draw the episode selection
my_snprintf( str, sizeof( str ), "iphone/button_ep%i.tga", e+1 );
iphoneDrawPicWithTouch( 96, 0, 384, 48, str );
// draw the individual maps
for ( m = 0 ; m < 10 ; m++ ) {
int x;
int y;
colour4_t colorSecret = { 32, 32, 32, 255 };
colour4_t colorNoTry = { 0, 0, 0, 255 };
colour4_t colorTried = { 80, 80, 0, 255 };
colour4_t colorCompleted = { 0, 80, 0, 255 };
if ( m == 9 ) {
sprintf( str, "SECRET" );
x = 120;
y = 90 + 160;
} else if ( m == 8 ) {
sprintf( str, "BOSS" );
x = 360;
y = 90 + 160;
} else {
sprintf( str, "LEVEL %i", m+1 );
x = 60 + 120 * ( m % 4 );
y = 90 + 80 * ( m / 4 );
}
unsigned char *color = colorNoTry;
// decide on the background color
int levelNum = e*10+m;
int ch = currentMap.mapFlags[s][levelNum];
// bit1 = attempted
// bit2 = completed
// bit3 = 100% kills
// bit4 = 100% secrets
// bit5 = 100% treasure
if ( m == 9 && !( ch & MF_TRIED ) ) {
color = colorSecret;
} if ( ch & MF_COMPLETED ) {
color = colorCompleted;
} else if ( ch & MF_TRIED ) {
color = colorTried;
} else {
color = colorNoTry;
}
// blink the level you are currently on
if ( ( iphoneFrameNum & 8 ) && levelNum == currentMap.map && e == currentMap.episode ) {
color = colorNoTry;
}
// draw the level text and check for button hit
if ( TouchDown( x-46, y-9, 88, 32 ) ) {
color = colorPressed;
}
R_Draw_Fill( x-46, y-9, 88, 32, color );
iphoneCenterText( x, y, str );
// draw awards
if ( ch & MF_KILLS ) {
iphoneDrawPic( x-46,y+23, 22, 22, "iphone/kills.tga" );
}
if ( ch & MF_SECRETS ) {
iphoneDrawPic( x-24,y+23, 22, 22, "iphone/secrets.tga" );
}
if ( ch & MF_TREASURE ) {
iphoneDrawPic( x-2,y+23, 22, 22, "iphone/treasure.tga" );
}
if ( ch & MF_TIME ) {
iphoneDrawPic( x+20,y+23, 22, 22, "iphone/partime.tga" );
}
// don't let them go to the secret level unless they earned it
if ( m == 9 && !( ch & MF_TRIED ) ) {
continue;
}
if ( TouchReleased( x - 46, y - 9, 88, 32 ) ) {
PL_NewGame( &Player );
iphoneStartMap( e, m, s );
}
}
}
/*
==================
iphoneStartIntermission
The framesFromNow value allow boss death animations to be triggered
==================
*/
void iphoneStartIntermission( int framesFromNow ) {
// this goes in the savegame if they save at the intermission point,
// which will cause it to come back up there on return
currentMap.levelCompleted = 1;
// mark this level as having been completed for the level selection menu
int mapNum = currentMap.episode * 10 + currentMap.map;
// note that this has been tried now
currentMap.mapFlags[currentMap.skill][mapNum] |= MF_COMPLETED;
// mark the awards
if ( levelstate.time / 70.0f < levelstate.fpartime * 60 ) { // fpartime is in minutes, time is in tics
currentMap.mapFlags[currentMap.skill][mapNum] |= MF_TIME;
}
if( levelstate.killed_monsters == levelstate.total_monsters ) {
currentMap.mapFlags[currentMap.skill][mapNum] |= MF_KILLS;
}
if( levelstate.found_secrets == levelstate.total_secrets ) {
currentMap.mapFlags[currentMap.skill][mapNum] |= MF_SECRETS;
}
if( levelstate.found_treasure == levelstate.total_treasure ) {
currentMap.mapFlags[currentMap.skill][mapNum] |= MF_TREASURE;
}
intermissionStartFrameNum = iphoneFrameNum;
if ( framesFromNow ) {
intermissionTriggerFrame = iphoneFrameNum + framesFromNow;
return;
}
intermissionTriggerFrame = 0;
menuState = IPM_INTERMISSION;
hasReleased = 0; // ensure touch up before skipping intermission
}
/*
==================
DrawDigit
==================
*/
void DrawDigit( int x, int y, int digit ) {
R_Bind( numberPics[digit]->texnum );
pfglBegin( GL_QUADS );
pfglTexCoord2f( 0, 0 ); pfglVertex2i( x, y );
pfglTexCoord2f( 1, 0 ); pfglVertex2i( x+32, y );
pfglTexCoord2f( 1, 1 ); pfglVertex2i( x+32, y+32 );
pfglTexCoord2f( 0, 1 ); pfglVertex2i( x, y+32 );
pfglEnd();
}
void DrawDoubleDigit( int x, int y, int number ) {
int step = 32;
if ( number >= 100 ) {
// cram three digits into the same space
DrawDigit( x-8, y, number / 100 );
number %= 100;
x += 16;
step = 24;
}
if ( number >= 10 ) {
DrawDigit( x, y, number / 10 );
number %= 10;
}
DrawDigit( x+step, y, number );
}
void DrawTime( int x, int y, int seconds ) {
int min = seconds / 60;
int sec = seconds % 60;
DrawDoubleDigit( x, y, min );
// DrawDoubleDigit( x+76, y, sec );
// always print both digits of seconds, so 2:00 prints correctly
DrawDigit( x+76, y, sec / 10 );
DrawDigit( x+76+32, y, sec % 10 );
}
void DrawRatio( int y, int got, int total, const char *bonusPic ) {
DrawDoubleDigit( 285, y, got );
DrawDoubleDigit( 361, y, total );
// draw the award icon
if ( got == total ) {
iphoneDrawPic( 480 - 40, y, 32, 32, bonusPic );
}
}
/*
==================
iphoneIntermission
==================
*/
void iphoneIntermission() {
int nextLevel = 0;
char str[128];
iphoneDrawPic( 0, 0, 480, 320, "iphone/intermission.tga" );
// episode
my_snprintf( str, sizeof( str ), "iphone/button_ep%i.tga", currentMap.episode+1 );
iphoneDrawPic( 0, 0, 384, 48, str );
// level
iphoneDrawNumber( 430, 0, currentMap.map + 1, 48, 48 );
// par / time
DrawTime( 51, 63, levelstate.fpartime * 60 ); // fpartime is in minutes
DrawTime( 285, 63, levelstate.time / 70 ); // levelstate.time is in tics
if ( levelstate.time/70 <= levelstate.fpartime * 60 ) {
iphoneDrawPic( 480 - 40, 63, 32, 32, "iphone/partime.tga" );
}
// ratios
DrawRatio( 124, levelstate.killed_monsters, levelstate.total_monsters, "iphone/kills.tga" );
DrawRatio( 189, levelstate.found_secrets, levelstate.total_secrets, "iphone/secrets.tga" );
DrawRatio( 255, levelstate.found_treasure, levelstate.total_treasure, "iphone/treasure.tga" );
// require all touches off before the intermission can exit
if ( numTouches == 0 && hasReleased == 0 ) {
hasReleased = 1;
return; // don't let the TouchReleased immediately fire
}
if ( !hasReleased ) {
return;
}
//----------------------
// tap for next level
//----------------------
if ( !TouchReleased( 0, 0, 480, 320 ) ) {
return;
}
menuState = IPM_GAME;
PL_NextLevel( &Player );
if( g_version->value == SPEAROFDESTINY ) {
}
else
{
int currentLevel = currentMap.episode * 10 + currentMap.map;
if( Player.playstate == ex_secretlevel ) {
switch( currentLevel ) {
case 0: nextLevel = 9; break;
case 10: nextLevel = 19; break;
case 26: nextLevel = 29; break;
case 32: nextLevel = 39; break;
case 44: nextLevel = 49; break;
case 52: nextLevel = 59; break;
}
} else {
switch ( currentLevel ) {
case 8:
case 18:
case 28:
case 38:
case 48:
case 58:
// go back to the episode select screen
menuState = IPM_VICTORY;
Sound_StartBGTrack( "music/URAHERO.ogg", "music/URAHERO.ogg" );
return;
case 9: nextLevel = 1; break;
case 19: nextLevel = 11; break;
case 29: nextLevel = 27; break;
case 39: nextLevel = 33; break;
case 49: nextLevel = 44; break;
case 59: nextLevel = 53; break;
default: nextLevel = currentLevel + 1; break;
}
}
}
iphoneStartMap( (nextLevel/10), (nextLevel%10), skill->value );
}
/*
==================
iphoneVictory
==================
*/
void iphoneVictory() {
iphoneDrawPic( 0, 0, 480, 320, "iphone/victory.tga" );
if ( !TouchReleased( 0, 0, 480, 320 ) ) {
return;
}
menuState = IPM_EPISODE;
}
/*
==================
iphoneAutomap
==================
*/
float mapOrigin[2];
float mapCenterY;
float mapScale;
typedef struct {
W8 x, y;
short texnum;
} mapTile_t;
#define MAPTILE_SPRITE_FLAG 1024
#define MAX_MAP_TILES 5000 // 4096 tiles + sprites
mapTile_t mapTiles[MAX_MAP_TILES];
int numMapTiles;
int MapTileSort( const void *a, const void *b ) {
return ((mapTile_t *)a)->texnum - ((mapTile_t *)b)->texnum;
}
void iphoneOpenAutomap() {
mapTile_t *mt = mapTiles;
numMapTiles = 0;
int x, y;
int xx, yy;
W32 tx, ty, n;
sprite_t* sprt;
mapOrigin[0] = Player.position.origin[0] / (float)TILEGLOBAL;
mapOrigin[1] = Player.position.origin[1] / (float)TILEGLOBAL;
mapScale = 10;
menuState = IPM_AUTOMAP;
// identify all the tiles to fill in
for( x = 0 ; x < 64; ++x ) {
for( y = 0 ; y < 64; ++y ) {
if ( r_world->tilemap[ x ][ y ] & ( WALL_TILE | PUSHWALL_TILE ) ) {
int visible = 0;
// check all 8 surrounding tiles for visibility
for ( xx = -1 ; xx <= 1 ; xx++ ) {
if ( x + xx < 0 ) {
continue;
}
if ( x + xx > 63 ) {
continue;
}
for ( yy = -1 ; yy <= 1 ; yy++ ) {
if ( y + yy < 0 ) {
continue;
}
if ( y + yy > 63 ) {
continue;
}
if ( r_world->tileEverVisible[x+xx][y+yy] ) {
visible = 1;
break;
}
}
}
if ( !visible ) {
continue;
}
int tex = r_world->wall_tex_y[ x ][ y ];
// special hack for the elevator switch tile, which is always
// facing east west for the switch, and north south for the railing
if ( tex == 40 && ( ( x>0 && r_world->tileEverVisible[x+1][y] )
|| ( x < 63 && r_world->tileEverVisible[x-1][y] ) ) ) {
tex = r_world->wall_tex_x[ x ][ y ];
}
if ( tex < 0x6a ) { // skip pushwall destinations
assert( tex >= 0 && tex < 1000 );
mt->x = x;
mt->y = y;
mt->texnum = tex;
if ( !wallTextures[mt->texnum] ) {
char name[1024];
my_snprintf( name, sizeof( name ), "walls/%.3d.tga", mt->texnum );
wallTextures[mt->texnum] = TM_FindTexture( name, TT_Wall );
assert( wallTextures[mt->texnum] );
}
mt++;
continue;
}
}
if ( !r_world->tileEverVisible[x][y] ) {
continue;
}
if( r_world->tilemap[ x ][ y ] & DOOR_TILE ) {
mt->x = x;
mt->y = y;
mt->texnum = r_world->Doors.DoorMap[ x ][ y ].texture;
if ( !wallTextures[ mt->texnum] ) {
char name[1024];
my_snprintf( name, sizeof( name ), "walls/%.3d.tga", mt->texnum );
wallTextures[mt->texnum] = TM_FindTexture( name, TT_Wall );
assert( wallTextures[mt->texnum] );
}
mt++;
continue;
}
// solid floor
mt->x = x;
mt->y = y;
mt->texnum = -1;
mt++;
}
}
// add solid sprite objects
for( n = 0, sprt = Spr_Sprites; n < n_of_sprt; ++n, ++sprt ) {
if( sprt->flags & SPRT_REMOVE ) {
continue;
}
if ( sprt->tex[0] >= SPR_GRD_S_1 ) {
// don't draw enemies, only static sprites
continue;
}
tx = sprt->tilex;
ty = sprt->tiley;
if( tx > 63 ) {
continue;
}
if( ty > 63 ) {
continue;
}
if ( !r_world->tileEverVisible[tx][ty] ) {
continue;
}
mt->x = tx;
mt->y = ty;
mt->texnum = MAPTILE_SPRITE_FLAG | sprt->tex[0];
mt++;
if ( !spriteTextures[ sprt->tex[0] ] ) {
char name[1024];
my_snprintf( name, sizeof( name ), "sprites/%.3d.tga", sprt->tex[0] );
spriteTextures[sprt->tex[0]] = TM_FindTexture( name, TT_Sprite );
}
if ( mt == &mapTiles[MAX_MAP_TILES] ) {
break; // list is full, some items won't show (shouldn't happen)
}
}
// sort the tiles to be drawn by texture
numMapTiles = mt - mapTiles;
qsort( mapTiles, numMapTiles, sizeof( mapTiles[0] ), MapTileSort );
}
void iphoneAutomap() {
mapTile_t *mt;
float px, py;
float angle, c, s;
int texnum;
// do touch ops before drawing for minimum latency
// drag for scrolling
if ( numTouches == 1 ) {
if ( numPrevTouches == 1 ) {
mapOrigin[0] -= ( touches[0][0] - prevTouches[0][0] ) / mapScale;
mapOrigin[1] += ( touches[0][1] - prevTouches[0][1] ) / mapScale;
}
}
// pinch for scaling
if ( numTouches == 2 ) {
if ( numPrevTouches == 2 ) {
float curDist = sqrt(
( touches[0][0] - touches[1][0] ) * ( touches[0][0] - touches[1][0] ) +
( touches[0][1] - touches[1][1] ) * ( touches[0][1] - touches[1][1] ) );
float prevDist = sqrt(
( prevTouches[0][0] - prevTouches[1][0] ) * ( prevTouches[0][0] - prevTouches[1][0] ) +
( prevTouches[0][1] - prevTouches[1][1] ) * ( prevTouches[0][1] - prevTouches[1][1] ) );
if ( prevDist == 0 ) {
prevDist = curDist;
}
mapScale *= curDist / prevDist;
if ( mapScale < 4 ) {
mapScale = 4;
}
if ( mapScale > 64 ) {
mapScale = 64;
}
}
}
// todo -- double tap for center on player
// set up matrix for drawing in tile units
pfglMatrixMode( GL_PROJECTION );
pfglLoadIdentity();
pfglRotatef( 90, 0, 0, 1 );
pfglOrtho( mapOrigin[0]-240.0 / mapScale, mapOrigin[0]+240.0 / mapScale,
mapOrigin[1]-160.0 / mapScale, mapOrigin[1]+160.0 / mapScale, -99999, 99999 );
mt = mapTiles;
texnum = 99999;
for ( int i = 0 ; i < numMapTiles ; i++, mt++ ) {
if ( texnum != mt->texnum ) {
texnum = mt->texnum;
if ( i != 0 ) {
pfglEnd();
}
if ( mt->texnum == -1 ) {
qglDisable( GL_TEXTURE_2D );
pfglColor3f( r_world->floorColour[0]/255.0, r_world->floorColour[1]/255.0, r_world->floorColour[2]/255.0 );
} else if ( mt->texnum & MAPTILE_SPRITE_FLAG ) {
qglEnable( GL_TEXTURE_2D );
pfglColor3f( 1, 1, 1 );
R_Bind( spriteTextures[mt->texnum&~MAPTILE_SPRITE_FLAG]->texnum );
} else {
qglEnable( GL_TEXTURE_2D );
pfglColor3f( 1, 1, 1 );
R_Bind( wallTextures[mt->texnum]->texnum );
}
pfglBegin( GL_QUADS );
}
pfglTexCoord2f( 0, 1 );
pfglVertex2i( mt->x, mt->y );
pfglTexCoord2f( 1, 1 );
pfglVertex2i( mt->x+1, mt->y );
pfglTexCoord2f( 1, 0 );
pfglVertex2i( mt->x+1, mt->y+1 );
pfglTexCoord2f( 0, 0 );
pfglVertex2i( mt->x, mt->y+1 );
}
pfglEnd();
// draw the yellow player triangle
qglDisable( GL_TEXTURE_2D );
if ( iphoneFrameNum & 8 ) { // blink it
pfglColor3f( 1, 1, 0 );
} else {
pfglColor3f( 0.5, 0.5, 0 );
}
angle = M_PI * Player.position.angle / (float)ANG_180;
c = cos( angle );
s = sin( angle );
px = Player.position.origin[0] / (float)TILEGLOBAL;
py = Player.position.origin[1] / (float)TILEGLOBAL;
pfglBegin( GL_TRIANGLES );
pfglVertex3f( px + c * 0.5, py + s * 0.5, 0 );
pfglVertex3f( px - c * 0.5 - s * 0.3, py - s * 0.5 + c * 0.3, 0 );
pfglVertex3f( px - c * 0.5 + s * 0.3, py - s * 0.5 - c * 0.3, 0 );
pfglEnd();
qglEnable( GL_TEXTURE_2D );
pfglColor3f( 1, 1, 1 );
// back button for returning to game
pfglMatrixMode( GL_PROJECTION );
pfglLoadIdentity();
pfglRotatef( 90, 0, 0, 1 );
pfglOrtho( 0, 480, 320, 0, -99999, 99999 );
if ( BackButton() ) {
menuState = IPM_GAME;
}
}
void iphoneDrawMenus() {
iphoneDrawPic( 0, 0, 480, 320, "iphone/background_1.tga" );
switch ( menuState ) {
case IPM_MAIN: iphoneMainMenu(); break;
case IPM_SKILL: iphoneSkillMenu(); break;
case IPM_EPISODE: iphoneEpisodeMenu(); break;
case IPM_MAPS: iphoneMapMenu(); break;
case IPM_CONTROLS: iphoneControlMenu(); break;
case IPM_INTERMISSION: iphoneIntermission(); break;
case IPM_VICTORY: iphoneVictory(); break;
case IPM_AUTOMAP: iphoneAutomap(); break;
}
}