From: Ingo Ruhnke Date: Wed, 17 Mar 2004 19:19:12 +0000 (+0000) Subject: - renamed *.c to *.cxx X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=82a761da8025c09c9eee2cf6753cc70c039046c0;p=supertux.git - renamed *.c to *.cxx SVN-Revision: 256 --- diff --git a/configure.ac b/configure.ac index 90e0b5ef1..fac9c086b 100644 --- a/configure.ac +++ b/configure.ac @@ -7,16 +7,17 @@ dnl =========================================================================== dnl Process this file with autoconf to produce a configure script. -AC_INIT(SuperTux, 0.0.6-cvs) -AC_CONFIG_SRCDIR([src/supertux.c]) +AC_INIT(SuperTux, 0.0.7-cvs) +AC_CONFIG_SRCDIR([src/supertux.cpp]) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE SDL_VERSION=1.2.4 AC_PROG_CC +AC_PROG_CXX AC_PROG_INSTALL -AC_LANG(C) +AC_LANG(C++) dnl Checks for header files. AC_HEADER_DIRENT @@ -33,7 +34,7 @@ AC_MSG_CHECKING(for gprof mode) AC_ARG_ENABLE(gprof, AC_HELP_STRING([--enable-gprof], [enable GNU profiling support]),, enable_gprof="no") if test "x${enable_gprof}" != "xno"; then - CFLAGS="$CFLAGS -pg" + CXXFLAGS="$CXXFLAGS -pg" AC_MSG_RESULT([enabled]) else AC_MSG_RESULT([disabled]) @@ -43,7 +44,7 @@ AC_MSG_CHECKING(for debug mode) AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable debugging mode]),, enable_debug="yes") if test "x${enable_debug}" != "xno"; then - CFLAGS="$CFLAGS -DDEBUG" + CXXFLAGS="$CXXFLAGS -DDEBUG" AC_MSG_RESULT([enabled]) else AC_MSG_RESULT([disabled]) @@ -53,10 +54,10 @@ AC_MSG_CHECKING(weather OpenGL should be used) AC_ARG_ENABLE(opengl, AC_HELP_STRING([--disable-opengl], [disable OpenGL support]),, enable_opengl="yes") if test "x${enable_opengl}" != "xno"; then - CFLAGS="$CFLAGS -D__OPENGL" + CXXFLAGS="$CXXFLAGS -D__OPENGL" AC_MSG_RESULT([yes]) else - CFLAGS="$CFLAGS -DNOOPENGL" + CXXFLAGS="$CXXFLAGS -DNOOPENGL" AC_MSG_RESULT([no]) fi @@ -64,26 +65,27 @@ AC_MSG_CHECKING(weather Sound should be supported) AC_ARG_ENABLE(sound, AC_HELP_STRING([--disable-sound], [disable sound support]),, enable_sound="yes") if test "x${enable_sound}" != "xno"; then - CFLAGS="$CFLAGS -D__SOUND" + CXXFLAGS="$CXXFLAGS -D__SOUND" AC_MSG_RESULT([yes]) else - CFLAGS="$CFLAGS -DNOSOUND" + CXXFLAGS="$CXXFLAGS -DNOSOUND" AC_MSG_RESULT([no]) fi dnl =========================================================================== dnl Check for SDL +AC_LANG_PUSH(C) AM_PATH_SDL($SDL_VERSION, :, AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])) - -CFLAGS="$CFLAGS $SDL_CFLAGS" +CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" LDFLAGS="$LDFLAGS $SDL_LIBS" +AC_LANG_POP() dnl Checks for additional libraries. if test "x${enable_sound}" != "xno"; then AC_CHECK_LIB(SDL_mixer, SDL_OpenAudio,, - [CFLAGS="$CFLAGS -DNOSOUND" + [CXXFLAGS="$CXXFLAGS -DNOSOUND" enable_sound="no"]) fi @@ -94,16 +96,16 @@ if test "x${enable_opengl}" != "xno"; then # else I end up with a black screen, might be a debian issue or a # local issue on my system, not sure AC_PATH_XTRA - CFLAGS="$CFLAGS $X_CFLAGS" + CXXFLAGS="$CXXFLAGS $X_CFLAGS" LDFLAGS="$LDFLAGS $X_LIBS" AC_CHECK_LIB(GL, glBegin,, - [CFLAGS="$CFLAGS -DNOOPENGL" + [CXXFLAGS="$CXXFLAGS -DNOOPENGL" enable_opengl="no"]) fi # FIXME: Evil -CFLAGS="$CFLAGS -DDATA_PREFIX='\"$datadir/supertux/\"' -DLINUX" +CXXFLAGS="$CXXFLAGS -DDATA_PREFIX='\"$datadir/supertux/\"' -DLINUX" dnl Checks for library functions. AC_CHECK_FUNCS(mkdir strdup strstr) diff --git a/src/Makefile.am b/src/Makefile.am index c0986a83b..41c9f34a4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,58 +1,58 @@ bin_PROGRAMS = supertux supertux_SOURCES = \ - badguy.c \ + badguy.cpp \ badguy.h \ - bitmask.c \ + bitmask.cpp \ bitmask.h \ - button.c \ + button.cpp \ button.h \ - collision.c \ + collision.cpp \ collision.h \ defines.h \ - gameloop.c \ + gameloop.cpp \ gameloop.h \ - globals.c \ + globals.cpp \ globals.h \ - high_scores.c \ + high_scores.cpp \ high_scores.h \ - intro.c \ + intro.cpp \ intro.h \ - level.c \ + level.cpp \ level.h \ - leveleditor.c \ + leveleditor.cpp \ leveleditor.h \ - lispreader.c \ + lispreader.cpp \ lispreader.h \ - menu.c \ + menu.cpp \ menu.h \ - physic.c \ + physic.cpp \ physic.h \ - player.c \ + player.cpp \ player.h \ - scene.c \ + scene.cpp \ scene.h \ - screen.c \ + screen.cpp \ screen.h \ - setup.c \ + setup.cpp \ setup.h \ - sound.c \ + sound.cpp \ sound.h \ - special.c \ + special.cpp \ special.h \ - supertux.c \ + supertux.cpp \ supertux.h \ - text.c \ + text.cpp \ text.h \ - texture.c \ + texture.cpp \ texture.h \ - timer.c \ + timer.cpp \ timer.h \ - title.c \ + title.cpp \ title.h \ - type.c \ + type.cpp \ type.h \ - world.c \ + world.cpp \ world.h # EOF # diff --git a/src/badguy.c b/src/badguy.c deleted file mode 100644 index 09703ecf1..000000000 --- a/src/badguy.c +++ /dev/null @@ -1,663 +0,0 @@ -// -// C Implementation: badguy -// -// Description: -// -// -// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "globals.h" -#include "defines.h" -#include "badguy.h" -#include "scene.h" -#include "screen.h" - -texture_type img_bsod_squished_left, img_bsod_squished_right, -img_bsod_falling_left, img_bsod_falling_right, -img_laptop_flat_left, img_laptop_flat_right, -img_laptop_falling_left, img_laptop_falling_right; -texture_type img_bsod_left[4], img_bsod_right[4], -img_laptop_left[3], img_laptop_right[3], -img_money_left[2], img_money_right[2]; -bitmask *bm_bsod; - -void badguy_create_bitmasks() -{ - /*bm_bsod = img_bsod_left[0];*/ -} - -void badguy_init(bad_guy_type* pbad, float x, float y, int kind) -{ - pbad->base.width = 32; - pbad->base.height = 32; - pbad->base.alive = YES; - pbad->mode = NORMAL; - pbad->dying = NO; - pbad->kind = kind; - pbad->base.x = x; - pbad->base.y = y; - pbad->base.xm = 1.3; - pbad->base.ym = 4.8; - pbad->old_base = pbad->base; - pbad->dir = LEFT; - pbad->seen = NO; - timer_init(&pbad->timer,YES); - physic_init(&pbad->physic); -} - -void badguy_action(bad_guy_type* pbad) -{ - - if (pbad->base.alive) - { - if (pbad->seen) - { - if (pbad->kind == BAD_BSOD) - { - /* --- BLUE SCREEN OF DEATH MONSTER: --- */ - - /* Move left/right: */ - - if (pbad->dying == NO || - pbad->dying == FALLING) - { - if (pbad->dir == RIGHT) - pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio; - else if (pbad->dir == LEFT) - pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio; - } - - - /* Move vertically: */ - - pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio; - - if (pbad->dying != FALLING) - collision_swept_object_map(&pbad->old_base,&pbad->base); - if (pbad->base.y > screen->h) - pbad->base.alive = NO; - - /* Bump into things horizontally: */ - - if (!pbad->dying) - { - if (issolid( pbad->base.x, (int) pbad->base.y + 16)) - { - pbad->dir = RIGHT; - } - else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16)) - { - pbad->dir = LEFT; - } - } - - /* Fall if we get off the ground: */ - - if (pbad->dying != FALLING) - { - if (!issolid(pbad->base.x+16, pbad->base.y + 32)) - { - if(!physic_is_set(&pbad->physic)) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,2.); - } - - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - else - { - /* Land: */ - - if (pbad->base.ym > 0) - { - pbad->base.y = (int)(pbad->base.y / 32) * 32; - pbad->base.ym = 0; - } - physic_init(&pbad->physic); - } - } - else - { - if(!physic_is_set(&pbad->physic)) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,2.); - } - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - - if (pbad->base.y > screen->h) - pbad->base.alive = NO; - } - else if (pbad->kind == BAD_LAPTOP) - { - /* --- LAPTOP MONSTER: --- */ - - /* Move left/right: */ - - if (pbad->mode == NORMAL || pbad->mode == KICK) - { - if (pbad->dying == NO || - pbad->dying == FALLING) - { - if (pbad->dir == RIGHT) - pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio; - else if (pbad->dir == LEFT) - pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio; - } - } - else if (pbad->mode == HELD) - { /* FIXME: The pbad object shouldn't know about pplayer objects. */ - /* If we're holding the laptop */ - pbad->dir=tux.dir; - if(pbad->dir==RIGHT) - { - pbad->base.x = tux.base.x + 16; - pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height; - } - else /* facing left */ - { - pbad->base.x = tux.base.x - 16; - pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height; - } - if(collision_object_map(&pbad->base)) - { - pbad->base.x = tux.base.x; - pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height; - } - - if(tux.input.fire != DOWN) /* SHOOT! */ - { - if(pbad->dir == LEFT) - pbad->base.x -= 24; - else - pbad->base.x += 24; - - pbad->mode=KICK; - pbad->base.ym-=8; - play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER); - } - } - - - /* Move vertically: */ - - if(pbad->mode != HELD) - pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio; - - if (pbad->dying != FALLING) - collision_swept_object_map(&pbad->old_base,&pbad->base); - if (pbad->base.y > screen->h) - pbad->base.alive = NO; - /* Bump into things horizontally: */ - - /* Bump into things horizontally: */ - - if (!pbad->dying) - { - int changed = pbad->dir; - if (issolid( pbad->base.x, (int) pbad->base.y + 16)) - { - pbad->dir = RIGHT; - } - else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16)) - { - pbad->dir = LEFT; - } - if(pbad->mode == KICK && changed != pbad->dir) - { - /* handle stereo sound */ - /* FIXME: In theory a badguy object doesn't know anything about player objects */ - if (tux.base.x > pbad->base.x) - play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER); - else if (tux.base.x < pbad->base.x) - play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER); - else - play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER); - } - - } - - - /* Fall if we get off the ground: */ - - if (pbad->dying != FALLING) - { - if (!issolid(pbad->base.x+16, pbad->base.y + 32)) - { - if(!physic_is_set(&pbad->physic)) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,0.); - } - - if(pbad->mode != HELD) - { - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - } - else - { - /* Land: */ - - if (pbad->base.ym > 0) - { - pbad->base.y = (int)(pbad->base.y / 32) * 32; - pbad->base.ym = 0; - } - physic_init(&pbad->physic); - } - } - else - { - if(!physic_is_set(&pbad->physic)) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,0.); - } - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - - - } - else if (pbad->kind == BAD_MONEY) - { - /* --- MONEY BAGS: --- */ - - - /* Move vertically: */ - - pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio; - - if (pbad->dying != FALLING) - collision_swept_object_map(&pbad->old_base,&pbad->base); - - if (pbad->base.y > screen->h) - pbad->base.alive = NO; - - if(physic_get_state(&pbad->physic) == -1) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,0.); - } - - if (pbad->dying != FALLING) - { - if(issolid(pbad->base.x, pbad->base.y + 32)) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,6.); - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - else if(issolid(pbad->base.x, pbad->base.y)) - { /* This works, but isn't the best solution imagineable */ - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,0.); - pbad->base.ym = physic_get_velocity(&pbad->physic); - ++pbad->base.y; - } - else - { - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - } - else - { - if(!physic_is_set(&pbad->physic)) - { - physic_set_state(&pbad->physic,PH_VT); - physic_set_start_vy(&pbad->physic,0.); - } - pbad->base.ym = physic_get_velocity(&pbad->physic); - } - } - else if (pbad->kind == -1) - {} - - } - else if (pbad->kind == -1) - {} - - - } - - /* Handle mode timer: */ - - if (pbad->mode == FLAT && pbad->mode != HELD) - { - if(!timer_check(&pbad->timer)) - { - pbad->mode = NORMAL; - pbad->base.xm = 4; - } - } - else if (pbad->mode == KICK) - { - timer_check(&pbad->timer); - } - - - /* Handle dying timer: */ - - if (pbad->dying == SQUISHED) - { - /* Remove it if time's up: */ - if(!timer_check(&pbad->timer)) - pbad->base.alive = NO; - } - - - /* Remove if it's far off the screen: */ - - if (pbad->base.x < scroll_x - OFFSCREEN_DISTANCE) - pbad->base.alive = NO; - else /* !seen */ - { - /* Once it's on screen, it's activated! */ - - if (pbad->base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE) - pbad->seen = YES; - } - /*}*/ -} - -void badguy_draw(bad_guy_type* pbad) -{ - if (pbad->base.alive && - pbad->base.x > scroll_x - 32 && - pbad->base.x < scroll_x + screen->w) - { - if (pbad->kind == BAD_BSOD) - { - /* --- BLUE SCREEN OF DEATH MONSTER: --- */ - - if (pbad->dying == NO) - { - /* Alive: */ - - if (pbad->dir == LEFT) - { - texture_draw(&img_bsod_left[(frame / 5) % 4], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_bsod_right[(frame / 5) % 4], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - else if (pbad->dying == FALLING) - { - /* Falling: */ - - if (pbad->dir == LEFT) - { - texture_draw(&img_bsod_falling_left, - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_bsod_falling_right, - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - else if (pbad->dying == SQUISHED) - { - /* Dying - Squished: */ - - if (pbad->dir == LEFT) - { - texture_draw(&img_bsod_squished_left, - pbad->base.x - scroll_x, - pbad->base.y + 24, - NO_UPDATE); - } - else - { - texture_draw(&img_bsod_squished_right, - pbad->base.x - scroll_x, - pbad->base.y + 24, - NO_UPDATE); - } - } - } - else if (pbad->kind == BAD_LAPTOP) - { - /* --- LAPTOP MONSTER: --- */ - - if (pbad->dying == NO) - { - /* Alive: */ - - if (pbad->mode == NORMAL) - { - /* Not flat: */ - - if (pbad->dir == LEFT) - { - texture_draw(&img_laptop_left[(frame / 5) % 3], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_laptop_right[(frame / 5) % 3], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - else - { - /* Flat: */ - - if (pbad->dir == LEFT) - { - texture_draw(&img_laptop_flat_left, - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_laptop_flat_right, - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - } - else if (pbad->dying == FALLING) - { - /* Falling: */ - - if (pbad->dir == LEFT) - { - texture_draw(&img_laptop_falling_left, - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_laptop_falling_right, - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - } - else if (pbad->kind == BAD_MONEY) - { - if (pbad->base.ym != 300 /* > -16*/) - { - if (pbad->dir == LEFT) - { - texture_draw(&img_money_left[0], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_money_right[0], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - else - { - if (pbad->dir == LEFT) - { - texture_draw(&img_money_left[1], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - else - { - texture_draw(&img_money_right[1], - pbad->base.x - scroll_x, - pbad->base.y, - NO_UPDATE); - } - } - } - else if (pbad->kind == -1) - {} - } -} - -void badguy_collision(bad_guy_type* pbad, void *p_c_object, int c_object) -{ - bad_guy_type* pbad_c = NULL; - player_type* pplayer_c = NULL; - - switch (c_object) - { - case CO_BULLET: - pbad->dying = FALLING; - pbad->base.ym = -8; - - /* Gain some points: */ - - if (pbad->kind == BAD_BSOD) - add_score(pbad->base.x - scroll_x, pbad->base.y, - 50 * score_multiplier); - else if (pbad->kind == BAD_LAPTOP) - add_score(pbad->base.x - scroll_x, pbad->base.y, - 25 * score_multiplier); - else if (pbad->kind == BAD_MONEY) - add_score(pbad->base.x - scroll_x, pbad->base.y, - 50 * score_multiplier); - - /* Play death sound: */ - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - break; - case CO_BADGUY: - pbad_c = (bad_guy_type*) p_c_object; - if (pbad->mode == NORMAL) - { - /* do nothing */ - } - else if(pbad->mode == KICK) - { - /* We're in kick mode, kill the other guy - and yourself(wuahaha) : */ - - pbad_c->dying = FALLING; - pbad_c->base.ym = -8; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - - add_score(pbad->base.x - scroll_x, - pbad->base.y, 100); - pbad_c->dying = FALLING; - - pbad->dying = FALLING; - pbad->base.ym = -8; - - add_score(pbad_c->base.x - scroll_x, - pbad_c->base.y, 100); - } - break; - case CO_PLAYER: - pplayer_c = (player_type*) p_c_object; - if(pbad->kind != BAD_MONEY) - { - if (pbad->kind == BAD_BSOD) - { - pbad->dying = SQUISHED; - timer_start(&pbad->timer,4000); - physic_set_state(&pplayer_c->vphysic,PH_VT); - physic_set_start_vy(&pplayer_c->vphysic,2.); - pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1; - - add_score(pbad->base.x - scroll_x, pbad->base.y, - 50 * score_multiplier); - - play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); - } - else if (pbad->kind == BAD_LAPTOP) - { - - if (pbad->mode == NORMAL || pbad->mode == KICK) - { - /* Flatten! */ - - play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); - pbad->mode = FLAT; - pbad->base.xm = 4; - - timer_start(&pbad->timer,10000); - - physic_set_state(&pplayer_c->vphysic,PH_VT); - physic_set_start_vy(&pplayer_c->vphysic,2.); - pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1; - } - else if (pbad->mode == FLAT) - { - /* Kick! */ - play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); - - if (pplayer_c->base.x <= pbad->base.x) - pbad->dir = RIGHT; - else - pbad->dir = LEFT; - - pbad->base.xm = 5; - pbad->mode = KICK; - - timer_start(&pbad->timer,5000); - } - - physic_set_state(&pplayer_c->vphysic,PH_VT); - physic_set_start_vy(&pplayer_c->vphysic,2.); - pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1; - - add_score(pbad->base.x - scroll_x, - pbad->base.y, - 25 * score_multiplier); - - /* play_sound(sounds[SND_SQUISH]); */ - } - score_multiplier++; - } - break; - } - -} diff --git a/src/badguy.cpp b/src/badguy.cpp new file mode 100644 index 000000000..09703ecf1 --- /dev/null +++ b/src/badguy.cpp @@ -0,0 +1,663 @@ +// +// C Implementation: badguy +// +// Description: +// +// +// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "globals.h" +#include "defines.h" +#include "badguy.h" +#include "scene.h" +#include "screen.h" + +texture_type img_bsod_squished_left, img_bsod_squished_right, +img_bsod_falling_left, img_bsod_falling_right, +img_laptop_flat_left, img_laptop_flat_right, +img_laptop_falling_left, img_laptop_falling_right; +texture_type img_bsod_left[4], img_bsod_right[4], +img_laptop_left[3], img_laptop_right[3], +img_money_left[2], img_money_right[2]; +bitmask *bm_bsod; + +void badguy_create_bitmasks() +{ + /*bm_bsod = img_bsod_left[0];*/ +} + +void badguy_init(bad_guy_type* pbad, float x, float y, int kind) +{ + pbad->base.width = 32; + pbad->base.height = 32; + pbad->base.alive = YES; + pbad->mode = NORMAL; + pbad->dying = NO; + pbad->kind = kind; + pbad->base.x = x; + pbad->base.y = y; + pbad->base.xm = 1.3; + pbad->base.ym = 4.8; + pbad->old_base = pbad->base; + pbad->dir = LEFT; + pbad->seen = NO; + timer_init(&pbad->timer,YES); + physic_init(&pbad->physic); +} + +void badguy_action(bad_guy_type* pbad) +{ + + if (pbad->base.alive) + { + if (pbad->seen) + { + if (pbad->kind == BAD_BSOD) + { + /* --- BLUE SCREEN OF DEATH MONSTER: --- */ + + /* Move left/right: */ + + if (pbad->dying == NO || + pbad->dying == FALLING) + { + if (pbad->dir == RIGHT) + pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio; + else if (pbad->dir == LEFT) + pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio; + } + + + /* Move vertically: */ + + pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio; + + if (pbad->dying != FALLING) + collision_swept_object_map(&pbad->old_base,&pbad->base); + if (pbad->base.y > screen->h) + pbad->base.alive = NO; + + /* Bump into things horizontally: */ + + if (!pbad->dying) + { + if (issolid( pbad->base.x, (int) pbad->base.y + 16)) + { + pbad->dir = RIGHT; + } + else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16)) + { + pbad->dir = LEFT; + } + } + + /* Fall if we get off the ground: */ + + if (pbad->dying != FALLING) + { + if (!issolid(pbad->base.x+16, pbad->base.y + 32)) + { + if(!physic_is_set(&pbad->physic)) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,2.); + } + + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + else + { + /* Land: */ + + if (pbad->base.ym > 0) + { + pbad->base.y = (int)(pbad->base.y / 32) * 32; + pbad->base.ym = 0; + } + physic_init(&pbad->physic); + } + } + else + { + if(!physic_is_set(&pbad->physic)) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,2.); + } + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + + if (pbad->base.y > screen->h) + pbad->base.alive = NO; + } + else if (pbad->kind == BAD_LAPTOP) + { + /* --- LAPTOP MONSTER: --- */ + + /* Move left/right: */ + + if (pbad->mode == NORMAL || pbad->mode == KICK) + { + if (pbad->dying == NO || + pbad->dying == FALLING) + { + if (pbad->dir == RIGHT) + pbad->base.x = pbad->base.x + pbad->base.xm * frame_ratio; + else if (pbad->dir == LEFT) + pbad->base.x = pbad->base.x - pbad->base.xm * frame_ratio; + } + } + else if (pbad->mode == HELD) + { /* FIXME: The pbad object shouldn't know about pplayer objects. */ + /* If we're holding the laptop */ + pbad->dir=tux.dir; + if(pbad->dir==RIGHT) + { + pbad->base.x = tux.base.x + 16; + pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height; + } + else /* facing left */ + { + pbad->base.x = tux.base.x - 16; + pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height; + } + if(collision_object_map(&pbad->base)) + { + pbad->base.x = tux.base.x; + pbad->base.y = tux.base.y + tux.base.height/1.5 - pbad->base.height; + } + + if(tux.input.fire != DOWN) /* SHOOT! */ + { + if(pbad->dir == LEFT) + pbad->base.x -= 24; + else + pbad->base.x += 24; + + pbad->mode=KICK; + pbad->base.ym-=8; + play_sound(sounds[SND_KICK],SOUND_CENTER_SPEAKER); + } + } + + + /* Move vertically: */ + + if(pbad->mode != HELD) + pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio; + + if (pbad->dying != FALLING) + collision_swept_object_map(&pbad->old_base,&pbad->base); + if (pbad->base.y > screen->h) + pbad->base.alive = NO; + /* Bump into things horizontally: */ + + /* Bump into things horizontally: */ + + if (!pbad->dying) + { + int changed = pbad->dir; + if (issolid( pbad->base.x, (int) pbad->base.y + 16)) + { + pbad->dir = RIGHT; + } + else if (issolid( pbad->base.x + pbad->base.width, (int) pbad->base.y + 16)) + { + pbad->dir = LEFT; + } + if(pbad->mode == KICK && changed != pbad->dir) + { + /* handle stereo sound */ + /* FIXME: In theory a badguy object doesn't know anything about player objects */ + if (tux.base.x > pbad->base.x) + play_sound(sounds[SND_RICOCHET], SOUND_LEFT_SPEAKER); + else if (tux.base.x < pbad->base.x) + play_sound(sounds[SND_RICOCHET], SOUND_RIGHT_SPEAKER); + else + play_sound(sounds[SND_RICOCHET], SOUND_CENTER_SPEAKER); + } + + } + + + /* Fall if we get off the ground: */ + + if (pbad->dying != FALLING) + { + if (!issolid(pbad->base.x+16, pbad->base.y + 32)) + { + if(!physic_is_set(&pbad->physic)) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,0.); + } + + if(pbad->mode != HELD) + { + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + } + else + { + /* Land: */ + + if (pbad->base.ym > 0) + { + pbad->base.y = (int)(pbad->base.y / 32) * 32; + pbad->base.ym = 0; + } + physic_init(&pbad->physic); + } + } + else + { + if(!physic_is_set(&pbad->physic)) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,0.); + } + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + + + } + else if (pbad->kind == BAD_MONEY) + { + /* --- MONEY BAGS: --- */ + + + /* Move vertically: */ + + pbad->base.y = pbad->base.y + pbad->base.ym * frame_ratio; + + if (pbad->dying != FALLING) + collision_swept_object_map(&pbad->old_base,&pbad->base); + + if (pbad->base.y > screen->h) + pbad->base.alive = NO; + + if(physic_get_state(&pbad->physic) == -1) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,0.); + } + + if (pbad->dying != FALLING) + { + if(issolid(pbad->base.x, pbad->base.y + 32)) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,6.); + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + else if(issolid(pbad->base.x, pbad->base.y)) + { /* This works, but isn't the best solution imagineable */ + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,0.); + pbad->base.ym = physic_get_velocity(&pbad->physic); + ++pbad->base.y; + } + else + { + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + } + else + { + if(!physic_is_set(&pbad->physic)) + { + physic_set_state(&pbad->physic,PH_VT); + physic_set_start_vy(&pbad->physic,0.); + } + pbad->base.ym = physic_get_velocity(&pbad->physic); + } + } + else if (pbad->kind == -1) + {} + + } + else if (pbad->kind == -1) + {} + + + } + + /* Handle mode timer: */ + + if (pbad->mode == FLAT && pbad->mode != HELD) + { + if(!timer_check(&pbad->timer)) + { + pbad->mode = NORMAL; + pbad->base.xm = 4; + } + } + else if (pbad->mode == KICK) + { + timer_check(&pbad->timer); + } + + + /* Handle dying timer: */ + + if (pbad->dying == SQUISHED) + { + /* Remove it if time's up: */ + if(!timer_check(&pbad->timer)) + pbad->base.alive = NO; + } + + + /* Remove if it's far off the screen: */ + + if (pbad->base.x < scroll_x - OFFSCREEN_DISTANCE) + pbad->base.alive = NO; + else /* !seen */ + { + /* Once it's on screen, it's activated! */ + + if (pbad->base.x <= scroll_x + screen->w + OFFSCREEN_DISTANCE) + pbad->seen = YES; + } + /*}*/ +} + +void badguy_draw(bad_guy_type* pbad) +{ + if (pbad->base.alive && + pbad->base.x > scroll_x - 32 && + pbad->base.x < scroll_x + screen->w) + { + if (pbad->kind == BAD_BSOD) + { + /* --- BLUE SCREEN OF DEATH MONSTER: --- */ + + if (pbad->dying == NO) + { + /* Alive: */ + + if (pbad->dir == LEFT) + { + texture_draw(&img_bsod_left[(frame / 5) % 4], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_bsod_right[(frame / 5) % 4], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + else if (pbad->dying == FALLING) + { + /* Falling: */ + + if (pbad->dir == LEFT) + { + texture_draw(&img_bsod_falling_left, + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_bsod_falling_right, + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + else if (pbad->dying == SQUISHED) + { + /* Dying - Squished: */ + + if (pbad->dir == LEFT) + { + texture_draw(&img_bsod_squished_left, + pbad->base.x - scroll_x, + pbad->base.y + 24, + NO_UPDATE); + } + else + { + texture_draw(&img_bsod_squished_right, + pbad->base.x - scroll_x, + pbad->base.y + 24, + NO_UPDATE); + } + } + } + else if (pbad->kind == BAD_LAPTOP) + { + /* --- LAPTOP MONSTER: --- */ + + if (pbad->dying == NO) + { + /* Alive: */ + + if (pbad->mode == NORMAL) + { + /* Not flat: */ + + if (pbad->dir == LEFT) + { + texture_draw(&img_laptop_left[(frame / 5) % 3], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_laptop_right[(frame / 5) % 3], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + else + { + /* Flat: */ + + if (pbad->dir == LEFT) + { + texture_draw(&img_laptop_flat_left, + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_laptop_flat_right, + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + } + else if (pbad->dying == FALLING) + { + /* Falling: */ + + if (pbad->dir == LEFT) + { + texture_draw(&img_laptop_falling_left, + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_laptop_falling_right, + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + } + else if (pbad->kind == BAD_MONEY) + { + if (pbad->base.ym != 300 /* > -16*/) + { + if (pbad->dir == LEFT) + { + texture_draw(&img_money_left[0], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_money_right[0], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + else + { + if (pbad->dir == LEFT) + { + texture_draw(&img_money_left[1], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + else + { + texture_draw(&img_money_right[1], + pbad->base.x - scroll_x, + pbad->base.y, + NO_UPDATE); + } + } + } + else if (pbad->kind == -1) + {} + } +} + +void badguy_collision(bad_guy_type* pbad, void *p_c_object, int c_object) +{ + bad_guy_type* pbad_c = NULL; + player_type* pplayer_c = NULL; + + switch (c_object) + { + case CO_BULLET: + pbad->dying = FALLING; + pbad->base.ym = -8; + + /* Gain some points: */ + + if (pbad->kind == BAD_BSOD) + add_score(pbad->base.x - scroll_x, pbad->base.y, + 50 * score_multiplier); + else if (pbad->kind == BAD_LAPTOP) + add_score(pbad->base.x - scroll_x, pbad->base.y, + 25 * score_multiplier); + else if (pbad->kind == BAD_MONEY) + add_score(pbad->base.x - scroll_x, pbad->base.y, + 50 * score_multiplier); + + /* Play death sound: */ + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + break; + case CO_BADGUY: + pbad_c = (bad_guy_type*) p_c_object; + if (pbad->mode == NORMAL) + { + /* do nothing */ + } + else if(pbad->mode == KICK) + { + /* We're in kick mode, kill the other guy + and yourself(wuahaha) : */ + + pbad_c->dying = FALLING; + pbad_c->base.ym = -8; + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + + add_score(pbad->base.x - scroll_x, + pbad->base.y, 100); + pbad_c->dying = FALLING; + + pbad->dying = FALLING; + pbad->base.ym = -8; + + add_score(pbad_c->base.x - scroll_x, + pbad_c->base.y, 100); + } + break; + case CO_PLAYER: + pplayer_c = (player_type*) p_c_object; + if(pbad->kind != BAD_MONEY) + { + if (pbad->kind == BAD_BSOD) + { + pbad->dying = SQUISHED; + timer_start(&pbad->timer,4000); + physic_set_state(&pplayer_c->vphysic,PH_VT); + physic_set_start_vy(&pplayer_c->vphysic,2.); + pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1; + + add_score(pbad->base.x - scroll_x, pbad->base.y, + 50 * score_multiplier); + + play_sound(sounds[SND_SQUISH], SOUND_CENTER_SPEAKER); + } + else if (pbad->kind == BAD_LAPTOP) + { + + if (pbad->mode == NORMAL || pbad->mode == KICK) + { + /* Flatten! */ + + play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); + pbad->mode = FLAT; + pbad->base.xm = 4; + + timer_start(&pbad->timer,10000); + + physic_set_state(&pplayer_c->vphysic,PH_VT); + physic_set_start_vy(&pplayer_c->vphysic,2.); + pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1; + } + else if (pbad->mode == FLAT) + { + /* Kick! */ + play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); + + if (pplayer_c->base.x <= pbad->base.x) + pbad->dir = RIGHT; + else + pbad->dir = LEFT; + + pbad->base.xm = 5; + pbad->mode = KICK; + + timer_start(&pbad->timer,5000); + } + + physic_set_state(&pplayer_c->vphysic,PH_VT); + physic_set_start_vy(&pplayer_c->vphysic,2.); + pplayer_c->base.y = pbad->base.y - pplayer_c->base.height - 1; + + add_score(pbad->base.x - scroll_x, + pbad->base.y, + 25 * score_multiplier); + + /* play_sound(sounds[SND_SQUISH]); */ + } + score_multiplier++; + } + break; + } + +} diff --git a/src/bitmask.c b/src/bitmask.c deleted file mode 100644 index a0be080ad..000000000 --- a/src/bitmask.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * bitmask.c 1.0 - * ------------- - * Simple and efficient bitmask collision detection routines - * Copyright (C) 2002 Ulf Ekstrom except for the bitcount function. - * - * > See the header file for more info. < - * - * Please email bugs and comments to Ulf Ekstrom, ulfek@ifm.liu.se - * - * 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 -#include -#include "bitmask.h" - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -bitmask *bitmask_create(int w, int h) -{ - bitmask *temp = (bitmask*) malloc(sizeof(bitmask)); - if (! temp) - return 0; - temp->w = w; - temp->h = h; - temp->bits = (long unsigned int*) calloc(h*((w - 1)/BITW_LEN + 1),sizeof(BITW)); - if (! temp->bits) - { - free(temp); - return 0; - } - else - return temp; -} - -bitmask *bitmask_create_SDL(SDL_Surface* surf) -{ - int w,h; - int bpp; - Uint8* p; - - bitmask *temp = (bitmask*) malloc(sizeof(bitmask)); - if (! temp) - return 0; - temp->w = surf->w; - temp->h = surf->h; - temp->bits = (long unsigned int*) calloc(surf->h*((surf->w - 1)/BITW_LEN + 1),sizeof(BITW)); - if (! temp->bits) - { - free(temp); - return 0; - } - else - return temp; - - bpp = surf->format->BytesPerPixel; - for(h = 0; h <= surf->h; ++h) - { - for(w = 0; w <= surf->h; ++w) - { - - p = (Uint8 *)surf->pixels + h*surf->pitch + w*bpp; - if(*p == 255) - bitmask_setbit(temp,w,h); - } - } - -} - -void bitmask_free(bitmask *m) -{ - free(m->bits); - free(m); -} - -int bitmask_overlap(const bitmask *a,const bitmask *b,int xoffset, int yoffset) -{ - BITW *a_entry,*a_end; - BITW *b_entry; - BITW *ap,*bp; - int shift,rshift,i,astripes,bstripes; - - if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) - return 0; - - if (xoffset >= 0) - { - if (yoffset >= 0) - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; - a_end = a_entry + MIN(b->h,a->h - yoffset); - b_entry = b->bits; - } - else - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN); - a_end = a_entry + MIN(b->h + yoffset,a->h); - b_entry = b->bits - yoffset; - } - shift = xoffset & BITW_MASK; - if (shift) - { - rshift = BITW_LEN - shift; - astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; - bstripes = (b->w - 1)/BITW_LEN + 1; - if (bstripes > astripes) /* zig-zag .. zig*/ - { - for (i=0;i> shift) & *bp++) - return 1; - a_entry += a->h; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;) - if ((*ap++ << rshift) & *bp++) - return 1; - b_entry += b->h; - } - for (ap = a_entry,bp = b_entry;ap < a_end;) - if ((*ap++ >> shift) & *bp++) - return 1; - return 0; - } - else /* zig-zag */ - { - for (i=0;i> shift) & *bp++) - return 1; - a_entry += a->h; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;) - if ((*ap++ << rshift) & *bp++) - return 1; - b_entry += b->h; - } - return 0; - } - } - else /* xoffset is a multiple of the stripe width, and the above routines wont work */ - { - astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; - for (i=0;ih; - a_end += a->h; - b_entry += b->h; - } - return 0; - } - } - else - return bitmask_overlap(b,a,-xoffset,-yoffset); -} - -/* Will hang if there are no bits set in w! */ -static INLINE int firstsetbit(BITW w) -{ - int i = 0; - while ((w & 1) == 0) - { - i++; - w/=2; - } - return i; -} - -/* x and y are given in the coordinates of mask a, and are untouched if the is no overlap */ -int bitmask_overlap_pos(const bitmask *a,const bitmask *b,int xoffset, int yoffset, int *x, int *y) -{ - BITW *a_entry,*a_end; - BITW *b_entry; - BITW *ap,*bp; - int shift,rshift,i,astripes,bstripes; - - if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) - return 0; - - if (xoffset >= 0) - { - if (yoffset >= 0) - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; - a_end = a_entry + MIN(b->h,a->h - yoffset); - b_entry = b->bits; - } - else - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN); - a_end = a_entry + MIN(b->h + yoffset,a->h); - b_entry = b->bits - yoffset; - } - shift = xoffset & BITW_MASK; - if (shift) - { - rshift = BITW_LEN - shift; - astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; - bstripes = (b->w - 1)/BITW_LEN + 1; - if (bstripes > astripes) /* zig-zag .. zig*/ - { - for (i=0;ibits) % a->h; - *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp << shift)); - return 1; - } - a_entry += a->h; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - if (*ap & (*bp >> rshift)) - { - *y = (ap - a->bits) % a->h; - *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp >> rshift)); - return 1; - } - b_entry += b->h; - } - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - if (*ap & (*bp << shift)) - { - *y = (ap - a->bits) % a->h; - *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp << shift)); - return 1; - } - return 0; - } - else /* zig-zag */ - { - for (i=0;ibits) % a->h; - *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp << shift)); - return 1; - } - a_entry += a->h; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - if (*ap & (*bp >> rshift)) - { - *y = (ap - a->bits) % a->h; - *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp >> rshift)); - return 1; - } - b_entry += b->h; - } - return 0; - } - } - else /* xoffset is a multiple of the stripe width, and the above routines won't work. */ - { - astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; - for (i=0;ibits) % a->h; - *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & *bp); - return 1; - } - } - a_entry += a->h; - a_end += a->h; - b_entry += b->h; - } - return 0; - } - } - else - { - if (bitmask_overlap_pos(b,a,-xoffset,-yoffset,x,y)) - { - *x += xoffset; - *y += yoffset; - return 1; - } - else - return 0; - } -} - - - -/* (C) Donald W. Gillies, 1992. All rights reserved. You may reuse - this bitcount() function anywhere you please as long as you retain - this Copyright Notice. */ -static INLINE int bitcount(unsigned long n) -{ - register unsigned long tmp; - return (tmp = (n) - (((n) >> 1) & 033333333333) - (((n) >> 2) & 011111111111),\ - tmp = ((tmp + (tmp >> 3)) & 030707070707), \ - tmp = (tmp + (tmp >> 6)), \ - tmp = (tmp + (tmp >> 12) + (tmp >> 24)) & 077); -} -/* End of Donald W. Gillies bitcount code */ - - -int bitmask_overlap_area(const bitmask *a,const bitmask *b,int xoffset, int yoffset) -{ - BITW *a_entry,*a_end; - BITW *b_entry; - BITW *ap,*bp; - int shift,rshift,i,astripes,bstripes; - int count = 0; - - if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) - return 0; - - if (xoffset >= 0) - { - if (yoffset >= 0) - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; - a_end = a_entry + MIN(b->h,a->h - yoffset); - b_entry = b->bits; - } - else - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN); - a_end = a_entry + MIN(b->h + yoffset,a->h); - b_entry = b->bits - yoffset; - } - shift = xoffset & BITW_MASK; - if (shift) - { - rshift = BITW_LEN - shift; - astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; - bstripes = (b->w - 1)/BITW_LEN + 1; - if (bstripes > astripes) /* zig-zag .. zig*/ - { - for (i=0;i> shift) | (*(ap + a->h) << rshift)) & *bp); - a_entry += a->h; - a_end += a->h; - b_entry += b->h; - } - for (ap = a_entry,bp = b_entry;ap < a_end;) - count += bitcount((*ap++ >> shift) & *bp++); - return count; - } - else /* zig-zag */ - { - for (i=0;i> shift) | (*(ap + a->h) << rshift)) & *bp); - a_entry += a->h; - a_end += a->h; - b_entry += b->h; - } - return count; - } - } - else /* xoffset is a multiple of the stripe width, and the above routines wont work */ - { - astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; - for (i=0;ih; - a_end += a->h; - b_entry += b->h; - } - return count; - } - } - else - return bitmask_overlap_area(b,a,-xoffset,-yoffset); -} - - -/* Draws mask b onto mask a (bitwise OR) */ -void bitmask_draw(bitmask *a,bitmask *b,int xoffset, int yoffset) -{ - BITW *a_entry,*a_end; - BITW *b_entry; - BITW *ap,*bp; - bitmask *swap; - int shift,rshift,i,astripes,bstripes; - - if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) - return; - - if (xoffset >= 0) - { - if (yoffset >= 0) - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; - a_end = a_entry + MIN(b->h,a->h - yoffset); - b_entry = b->bits; - } - else - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN); - a_end = a_entry + MIN(b->h + yoffset,a->h); - b_entry = b->bits - yoffset; - } - shift = xoffset & BITW_MASK; - if (shift) - { - rshift = BITW_LEN - shift; - astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; - bstripes = (b->w - 1)/BITW_LEN + 1; - if (bstripes > astripes) /* zig-zag .. zig*/ - { - for (i=0;ih; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - *ap |= (*bp >> rshift); - b_entry += b->h; - } - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - *ap |= (*bp << shift); - return; - } - else /* zig-zag */ - { - for (i=0;ih; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - *ap |= (*bp >> rshift); - b_entry += b->h; - } - return; - } - } - else /* xoffset is a multiple of the stripe width, and the above routines won't work. */ - { - astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; - for (i=0;ih; - a_end += a->h; - b_entry += b->h; - } - return; - } - } - else - { - /* 'Swapping' arguments to be able to almost reuse the code above */ - swap = a; - a = b; - b = swap; - xoffset *= -1; - yoffset *= -1; - - if (yoffset >= 0) - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; - a_end = a_entry + MIN(b->h,a->h - yoffset); - b_entry = b->bits; - } - else - { - a_entry = a->bits + a->h*(xoffset/BITW_LEN); - a_end = a_entry + MIN(b->h + yoffset,a->h); - b_entry = b->bits - yoffset; - } - shift = xoffset & BITW_MASK; - if (shift) - { - rshift = BITW_LEN - shift; - astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; - bstripes = (b->w - 1)/BITW_LEN + 1; - if (bstripes > astripes) /* zig-zag .. zig*/ - { - for (i=0;i> shift); - a_entry += a->h; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - *bp |= (*ap <h; - } - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - *bp |= (*ap >> shift); - return; - } - else /* zig-zag */ - { - for (i=0;i> shift); - a_entry += a->h; - a_end += a->h; - for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) - *bp |= (*ap << rshift); - b_entry += b->h; - } - return; - } - } - else /* xoffset is a multiple of the stripe width, and the above routines won't work. */ - { - astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; - for (i=0;ih; - a_end += a->h; - b_entry += b->h; - } - return; - } - } -} diff --git a/src/bitmask.cpp b/src/bitmask.cpp new file mode 100644 index 000000000..a0be080ad --- /dev/null +++ b/src/bitmask.cpp @@ -0,0 +1,554 @@ +/* + * bitmask.c 1.0 + * ------------- + * Simple and efficient bitmask collision detection routines + * Copyright (C) 2002 Ulf Ekstrom except for the bitcount function. + * + * > See the header file for more info. < + * + * Please email bugs and comments to Ulf Ekstrom, ulfek@ifm.liu.se + * + * 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 +#include +#include "bitmask.h" + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +bitmask *bitmask_create(int w, int h) +{ + bitmask *temp = (bitmask*) malloc(sizeof(bitmask)); + if (! temp) + return 0; + temp->w = w; + temp->h = h; + temp->bits = (long unsigned int*) calloc(h*((w - 1)/BITW_LEN + 1),sizeof(BITW)); + if (! temp->bits) + { + free(temp); + return 0; + } + else + return temp; +} + +bitmask *bitmask_create_SDL(SDL_Surface* surf) +{ + int w,h; + int bpp; + Uint8* p; + + bitmask *temp = (bitmask*) malloc(sizeof(bitmask)); + if (! temp) + return 0; + temp->w = surf->w; + temp->h = surf->h; + temp->bits = (long unsigned int*) calloc(surf->h*((surf->w - 1)/BITW_LEN + 1),sizeof(BITW)); + if (! temp->bits) + { + free(temp); + return 0; + } + else + return temp; + + bpp = surf->format->BytesPerPixel; + for(h = 0; h <= surf->h; ++h) + { + for(w = 0; w <= surf->h; ++w) + { + + p = (Uint8 *)surf->pixels + h*surf->pitch + w*bpp; + if(*p == 255) + bitmask_setbit(temp,w,h); + } + } + +} + +void bitmask_free(bitmask *m) +{ + free(m->bits); + free(m); +} + +int bitmask_overlap(const bitmask *a,const bitmask *b,int xoffset, int yoffset) +{ + BITW *a_entry,*a_end; + BITW *b_entry; + BITW *ap,*bp; + int shift,rshift,i,astripes,bstripes; + + if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) + return 0; + + if (xoffset >= 0) + { + if (yoffset >= 0) + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; + a_end = a_entry + MIN(b->h,a->h - yoffset); + b_entry = b->bits; + } + else + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN); + a_end = a_entry + MIN(b->h + yoffset,a->h); + b_entry = b->bits - yoffset; + } + shift = xoffset & BITW_MASK; + if (shift) + { + rshift = BITW_LEN - shift; + astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; + bstripes = (b->w - 1)/BITW_LEN + 1; + if (bstripes > astripes) /* zig-zag .. zig*/ + { + for (i=0;i> shift) & *bp++) + return 1; + a_entry += a->h; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;) + if ((*ap++ << rshift) & *bp++) + return 1; + b_entry += b->h; + } + for (ap = a_entry,bp = b_entry;ap < a_end;) + if ((*ap++ >> shift) & *bp++) + return 1; + return 0; + } + else /* zig-zag */ + { + for (i=0;i> shift) & *bp++) + return 1; + a_entry += a->h; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;) + if ((*ap++ << rshift) & *bp++) + return 1; + b_entry += b->h; + } + return 0; + } + } + else /* xoffset is a multiple of the stripe width, and the above routines wont work */ + { + astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; + for (i=0;ih; + a_end += a->h; + b_entry += b->h; + } + return 0; + } + } + else + return bitmask_overlap(b,a,-xoffset,-yoffset); +} + +/* Will hang if there are no bits set in w! */ +static INLINE int firstsetbit(BITW w) +{ + int i = 0; + while ((w & 1) == 0) + { + i++; + w/=2; + } + return i; +} + +/* x and y are given in the coordinates of mask a, and are untouched if the is no overlap */ +int bitmask_overlap_pos(const bitmask *a,const bitmask *b,int xoffset, int yoffset, int *x, int *y) +{ + BITW *a_entry,*a_end; + BITW *b_entry; + BITW *ap,*bp; + int shift,rshift,i,astripes,bstripes; + + if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) + return 0; + + if (xoffset >= 0) + { + if (yoffset >= 0) + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; + a_end = a_entry + MIN(b->h,a->h - yoffset); + b_entry = b->bits; + } + else + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN); + a_end = a_entry + MIN(b->h + yoffset,a->h); + b_entry = b->bits - yoffset; + } + shift = xoffset & BITW_MASK; + if (shift) + { + rshift = BITW_LEN - shift; + astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; + bstripes = (b->w - 1)/BITW_LEN + 1; + if (bstripes > astripes) /* zig-zag .. zig*/ + { + for (i=0;ibits) % a->h; + *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp << shift)); + return 1; + } + a_entry += a->h; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + if (*ap & (*bp >> rshift)) + { + *y = (ap - a->bits) % a->h; + *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp >> rshift)); + return 1; + } + b_entry += b->h; + } + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + if (*ap & (*bp << shift)) + { + *y = (ap - a->bits) % a->h; + *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp << shift)); + return 1; + } + return 0; + } + else /* zig-zag */ + { + for (i=0;ibits) % a->h; + *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp << shift)); + return 1; + } + a_entry += a->h; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + if (*ap & (*bp >> rshift)) + { + *y = (ap - a->bits) % a->h; + *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & (*bp >> rshift)); + return 1; + } + b_entry += b->h; + } + return 0; + } + } + else /* xoffset is a multiple of the stripe width, and the above routines won't work. */ + { + astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; + for (i=0;ibits) % a->h; + *x = ((ap - a->bits) / a->h)*BITW_LEN + firstsetbit(*ap & *bp); + return 1; + } + } + a_entry += a->h; + a_end += a->h; + b_entry += b->h; + } + return 0; + } + } + else + { + if (bitmask_overlap_pos(b,a,-xoffset,-yoffset,x,y)) + { + *x += xoffset; + *y += yoffset; + return 1; + } + else + return 0; + } +} + + + +/* (C) Donald W. Gillies, 1992. All rights reserved. You may reuse + this bitcount() function anywhere you please as long as you retain + this Copyright Notice. */ +static INLINE int bitcount(unsigned long n) +{ + register unsigned long tmp; + return (tmp = (n) - (((n) >> 1) & 033333333333) - (((n) >> 2) & 011111111111),\ + tmp = ((tmp + (tmp >> 3)) & 030707070707), \ + tmp = (tmp + (tmp >> 6)), \ + tmp = (tmp + (tmp >> 12) + (tmp >> 24)) & 077); +} +/* End of Donald W. Gillies bitcount code */ + + +int bitmask_overlap_area(const bitmask *a,const bitmask *b,int xoffset, int yoffset) +{ + BITW *a_entry,*a_end; + BITW *b_entry; + BITW *ap,*bp; + int shift,rshift,i,astripes,bstripes; + int count = 0; + + if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) + return 0; + + if (xoffset >= 0) + { + if (yoffset >= 0) + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; + a_end = a_entry + MIN(b->h,a->h - yoffset); + b_entry = b->bits; + } + else + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN); + a_end = a_entry + MIN(b->h + yoffset,a->h); + b_entry = b->bits - yoffset; + } + shift = xoffset & BITW_MASK; + if (shift) + { + rshift = BITW_LEN - shift; + astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; + bstripes = (b->w - 1)/BITW_LEN + 1; + if (bstripes > astripes) /* zig-zag .. zig*/ + { + for (i=0;i> shift) | (*(ap + a->h) << rshift)) & *bp); + a_entry += a->h; + a_end += a->h; + b_entry += b->h; + } + for (ap = a_entry,bp = b_entry;ap < a_end;) + count += bitcount((*ap++ >> shift) & *bp++); + return count; + } + else /* zig-zag */ + { + for (i=0;i> shift) | (*(ap + a->h) << rshift)) & *bp); + a_entry += a->h; + a_end += a->h; + b_entry += b->h; + } + return count; + } + } + else /* xoffset is a multiple of the stripe width, and the above routines wont work */ + { + astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; + for (i=0;ih; + a_end += a->h; + b_entry += b->h; + } + return count; + } + } + else + return bitmask_overlap_area(b,a,-xoffset,-yoffset); +} + + +/* Draws mask b onto mask a (bitwise OR) */ +void bitmask_draw(bitmask *a,bitmask *b,int xoffset, int yoffset) +{ + BITW *a_entry,*a_end; + BITW *b_entry; + BITW *ap,*bp; + bitmask *swap; + int shift,rshift,i,astripes,bstripes; + + if ((xoffset >= a->w) || (yoffset >= a->h) || (yoffset <= - b->h)) + return; + + if (xoffset >= 0) + { + if (yoffset >= 0) + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; + a_end = a_entry + MIN(b->h,a->h - yoffset); + b_entry = b->bits; + } + else + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN); + a_end = a_entry + MIN(b->h + yoffset,a->h); + b_entry = b->bits - yoffset; + } + shift = xoffset & BITW_MASK; + if (shift) + { + rshift = BITW_LEN - shift; + astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; + bstripes = (b->w - 1)/BITW_LEN + 1; + if (bstripes > astripes) /* zig-zag .. zig*/ + { + for (i=0;ih; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + *ap |= (*bp >> rshift); + b_entry += b->h; + } + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + *ap |= (*bp << shift); + return; + } + else /* zig-zag */ + { + for (i=0;ih; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + *ap |= (*bp >> rshift); + b_entry += b->h; + } + return; + } + } + else /* xoffset is a multiple of the stripe width, and the above routines won't work. */ + { + astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; + for (i=0;ih; + a_end += a->h; + b_entry += b->h; + } + return; + } + } + else + { + /* 'Swapping' arguments to be able to almost reuse the code above */ + swap = a; + a = b; + b = swap; + xoffset *= -1; + yoffset *= -1; + + if (yoffset >= 0) + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN) + yoffset; + a_end = a_entry + MIN(b->h,a->h - yoffset); + b_entry = b->bits; + } + else + { + a_entry = a->bits + a->h*(xoffset/BITW_LEN); + a_end = a_entry + MIN(b->h + yoffset,a->h); + b_entry = b->bits - yoffset; + } + shift = xoffset & BITW_MASK; + if (shift) + { + rshift = BITW_LEN - shift; + astripes = (a->w - 1)/BITW_LEN - xoffset/BITW_LEN; + bstripes = (b->w - 1)/BITW_LEN + 1; + if (bstripes > astripes) /* zig-zag .. zig*/ + { + for (i=0;i> shift); + a_entry += a->h; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + *bp |= (*ap <h; + } + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + *bp |= (*ap >> shift); + return; + } + else /* zig-zag */ + { + for (i=0;i> shift); + a_entry += a->h; + a_end += a->h; + for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++) + *bp |= (*ap << rshift); + b_entry += b->h; + } + return; + } + } + else /* xoffset is a multiple of the stripe width, and the above routines won't work. */ + { + astripes = (MIN(b->w,a->w - xoffset) - 1)/BITW_LEN + 1; + for (i=0;ih; + a_end += a->h; + b_entry += b->h; + } + return; + } + } +} diff --git a/src/button.c b/src/button.c deleted file mode 100644 index b209969cb..000000000 --- a/src/button.c +++ /dev/null @@ -1,272 +0,0 @@ -// -// C Implementation: button -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include -#include -#include "setup.h" -#include "screen.h" -#include "globals.h" -#include "button.h" - -void button_load(button_type* pbutton,char* icon_file, char* info, SDLKey shortcut, int x, int y) -{ - char filename[1024]; - - if(icon_file != NULL) - { - snprintf(filename, 1024, "%s/%s", DATA_PREFIX, icon_file); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); - } - else - { - snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); - } - texture_load(&pbutton->icon,filename,USE_ALPHA); - - if(info == NULL) - { - pbutton->info = NULL; - } - else - { - pbutton->info = (char*) malloc(sizeof(char)*(strlen(info) + 1)); - strcpy(pbutton->info,info); - } - - pbutton->shortcut = shortcut; - - pbutton->x = x; - pbutton->y = y; - pbutton->w = pbutton->icon.w; - pbutton->h = pbutton->icon.h; - pbutton->tag = -1; - pbutton->state = -1; - pbutton->show_info = NO; - pbutton->bkgd = NULL; -} - -button_type* button_change_icon(button_type* pbutton,char* icon_file) -{ - char filename[1024]; - - if(icon_file != NULL) - { - snprintf(filename, 1024, "%s/%s", DATA_PREFIX, icon_file); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); - } - else - { - snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); - } - - texture_free(&pbutton->icon); - texture_load(&pbutton->icon,filename,USE_ALPHA); -} - -button_type* button_create(char* icon_file, char* info, SDLKey shortcut, int x, int y) -{ - button_type* pnew_button = (button_type*) malloc(sizeof(button_type)); - button_load(pnew_button,icon_file, info, shortcut, x, y); - return pnew_button; -} - -void button_draw(button_type* pbutton) -{ - fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200); - fillrect(pbutton->x+1,pbutton->y+1,pbutton->w-2,pbutton->h-2,175,175,175,200); - if(pbutton->bkgd != NULL) - { - texture_draw(pbutton->bkgd,pbutton->x,pbutton->y,NO_UPDATE); - } - texture_draw(&pbutton->icon,pbutton->x,pbutton->y,NO_UPDATE); - if(pbutton->show_info == YES) - { - char str[80]; - int i = -32; - - if(0 > pbutton->x - (int)strlen(pbutton->info) * white_small_text.w) - i = pbutton->w + strlen(pbutton->info) * white_small_text.w; - - if(pbutton->info) - text_draw(&white_small_text, pbutton->info, i + pbutton->x - strlen(pbutton->info) * white_small_text.w, pbutton->y, 1, NO_UPDATE); - sprintf(str,"(%s)", SDL_GetKeyName(pbutton->shortcut)); - text_draw(&white_small_text, str, i + pbutton->x - strlen(str) * white_small_text.w, pbutton->y + white_small_text.h+2, 1, NO_UPDATE); - } - if(pbutton->state == BN_PRESSED) - fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200); - else if(pbutton->state == BN_HOVER) - fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,150,150,150,128); -} - -void button_free(button_type* pbutton) -{ - free(pbutton->info); - texture_free(&pbutton->icon); -} - -void button_event(button_type* pbutton, SDL_Event *event) -{ - SDLKey key = event->key.keysym.sym; - - if(event->motion.x > pbutton->x && event->motion.x < pbutton->x + pbutton->w && - event->motion.y > pbutton->y && event->motion.y < pbutton->y + pbutton->h) - { - if(event->type == SDL_MOUSEBUTTONDOWN) - { - if(event->button.button == SDL_BUTTON_LEFT) - { - pbutton->state = BN_PRESSED; - } - else - { - pbutton->show_info = YES; - } - } - else if(event->type == SDL_MOUSEBUTTONUP) - { - if(event->button.button == SDL_BUTTON_LEFT && pbutton->state == BN_PRESSED) - { - pbutton->state = BN_CLICKED; - } - else if(event->button.button != SDL_BUTTON_LEFT && pbutton->state != BN_PRESSED) - { - pbutton->show_info = YES; - } - } - - if(pbutton->state != BN_PRESSED && pbutton->state != BN_CLICKED) - { - pbutton->state = BN_HOVER; - } - } - else if(event->type != SDL_KEYDOWN && event->type != SDL_KEYUP) - { - pbutton->state = -1; - if(pbutton->show_info) - { - pbutton->show_info = NO; - } - } - - if(event->type == SDL_KEYDOWN) - { - if(key == pbutton->shortcut) - pbutton->state = BN_PRESSED; - } - else if(event->type == SDL_KEYUP) - { - if(pbutton->state == BN_PRESSED && key == pbutton->shortcut) - pbutton->state = BN_CLICKED; - } - else if(event->type == SDL_MOUSEMOTION) - { - - if(pbutton->show_info) - { - pbutton->show_info = NO; - } - } -} - -int button_get_state(button_type* pbutton) -{ - int state; - if(pbutton->state == BN_CLICKED) - { - state = pbutton->state; - pbutton->state = -1; - return state; - } - else - { - return pbutton->state; - } -} - -void button_panel_init(button_panel_type* pbutton_panel, int x, int y, int w, int h) -{ - pbutton_panel->num_items = 0; - pbutton_panel->item = NULL; - pbutton_panel->x = x; - pbutton_panel->y = y; - pbutton_panel->w = w; - pbutton_panel->h = h; - pbutton_panel->hidden = NO; -} - -button_type* button_panel_event(button_panel_type* pbutton_panel, SDL_Event* event) -{ - if(pbutton_panel->hidden == NO) - { - int i; - for(i = 0; i < pbutton_panel->num_items; ++i) - { - button_event(&pbutton_panel->item[i],event); - if(pbutton_panel->item[i].state != -1) - return &pbutton_panel->item[i]; - } - return NULL; - } - else - { - return NULL; - } -} - -void button_panel_free(button_panel_type* pbutton_panel) -{ - int i; - for(i = 0; i < pbutton_panel->num_items; ++i) - { - button_free(&pbutton_panel->item[i]); - } - if(pbutton_panel->num_items) - free(pbutton_panel->item); -} - -void button_panel_draw(button_panel_type* pbutton_panel) -{ - if(pbutton_panel->hidden == NO) - { - int i; - fillrect(pbutton_panel->x,pbutton_panel->y,pbutton_panel->w,pbutton_panel->h,100,100,100,200); - for(i = 0; i < pbutton_panel->num_items; ++i) - { - button_draw(&pbutton_panel->item[i]); - } - } -} - -void button_panel_additem(button_panel_type* pbutton_panel, button_type* pbutton, int tag) -{ - int max_cols, row, col; - - ++pbutton_panel->num_items; - pbutton_panel->item = (button_type*) realloc(pbutton_panel->item, sizeof(button_type) * pbutton_panel->num_items); - memcpy(&pbutton_panel->item[pbutton_panel->num_items-1],pbutton,sizeof(button_type)); - free(pbutton); - - /* A button_panel takes control of the buttons it contains and arranges them */ - - max_cols = pbutton_panel->w / 32; - - row = (pbutton_panel->num_items-1) / max_cols; - col = (pbutton_panel->num_items-1) % max_cols; - - pbutton_panel->item[pbutton_panel->num_items-1].x = pbutton_panel->x + col * 32; - pbutton_panel->item[pbutton_panel->num_items-1].y = pbutton_panel->y + row * 32; - pbutton_panel->item[pbutton_panel->num_items-1].tag = tag; - -} - diff --git a/src/button.cpp b/src/button.cpp new file mode 100644 index 000000000..b209969cb --- /dev/null +++ b/src/button.cpp @@ -0,0 +1,272 @@ +// +// C Implementation: button +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include +#include "setup.h" +#include "screen.h" +#include "globals.h" +#include "button.h" + +void button_load(button_type* pbutton,char* icon_file, char* info, SDLKey shortcut, int x, int y) +{ + char filename[1024]; + + if(icon_file != NULL) + { + snprintf(filename, 1024, "%s/%s", DATA_PREFIX, icon_file); + if(!faccessible(filename)) + snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); + } + else + { + snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); + } + texture_load(&pbutton->icon,filename,USE_ALPHA); + + if(info == NULL) + { + pbutton->info = NULL; + } + else + { + pbutton->info = (char*) malloc(sizeof(char)*(strlen(info) + 1)); + strcpy(pbutton->info,info); + } + + pbutton->shortcut = shortcut; + + pbutton->x = x; + pbutton->y = y; + pbutton->w = pbutton->icon.w; + pbutton->h = pbutton->icon.h; + pbutton->tag = -1; + pbutton->state = -1; + pbutton->show_info = NO; + pbutton->bkgd = NULL; +} + +button_type* button_change_icon(button_type* pbutton,char* icon_file) +{ + char filename[1024]; + + if(icon_file != NULL) + { + snprintf(filename, 1024, "%s/%s", DATA_PREFIX, icon_file); + if(!faccessible(filename)) + snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); + } + else + { + snprintf(filename, 1024, "%s/images/icons/default-icon.png", DATA_PREFIX); + } + + texture_free(&pbutton->icon); + texture_load(&pbutton->icon,filename,USE_ALPHA); +} + +button_type* button_create(char* icon_file, char* info, SDLKey shortcut, int x, int y) +{ + button_type* pnew_button = (button_type*) malloc(sizeof(button_type)); + button_load(pnew_button,icon_file, info, shortcut, x, y); + return pnew_button; +} + +void button_draw(button_type* pbutton) +{ + fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200); + fillrect(pbutton->x+1,pbutton->y+1,pbutton->w-2,pbutton->h-2,175,175,175,200); + if(pbutton->bkgd != NULL) + { + texture_draw(pbutton->bkgd,pbutton->x,pbutton->y,NO_UPDATE); + } + texture_draw(&pbutton->icon,pbutton->x,pbutton->y,NO_UPDATE); + if(pbutton->show_info == YES) + { + char str[80]; + int i = -32; + + if(0 > pbutton->x - (int)strlen(pbutton->info) * white_small_text.w) + i = pbutton->w + strlen(pbutton->info) * white_small_text.w; + + if(pbutton->info) + text_draw(&white_small_text, pbutton->info, i + pbutton->x - strlen(pbutton->info) * white_small_text.w, pbutton->y, 1, NO_UPDATE); + sprintf(str,"(%s)", SDL_GetKeyName(pbutton->shortcut)); + text_draw(&white_small_text, str, i + pbutton->x - strlen(str) * white_small_text.w, pbutton->y + white_small_text.h+2, 1, NO_UPDATE); + } + if(pbutton->state == BN_PRESSED) + fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,75,75,75,200); + else if(pbutton->state == BN_HOVER) + fillrect(pbutton->x,pbutton->y,pbutton->w,pbutton->h,150,150,150,128); +} + +void button_free(button_type* pbutton) +{ + free(pbutton->info); + texture_free(&pbutton->icon); +} + +void button_event(button_type* pbutton, SDL_Event *event) +{ + SDLKey key = event->key.keysym.sym; + + if(event->motion.x > pbutton->x && event->motion.x < pbutton->x + pbutton->w && + event->motion.y > pbutton->y && event->motion.y < pbutton->y + pbutton->h) + { + if(event->type == SDL_MOUSEBUTTONDOWN) + { + if(event->button.button == SDL_BUTTON_LEFT) + { + pbutton->state = BN_PRESSED; + } + else + { + pbutton->show_info = YES; + } + } + else if(event->type == SDL_MOUSEBUTTONUP) + { + if(event->button.button == SDL_BUTTON_LEFT && pbutton->state == BN_PRESSED) + { + pbutton->state = BN_CLICKED; + } + else if(event->button.button != SDL_BUTTON_LEFT && pbutton->state != BN_PRESSED) + { + pbutton->show_info = YES; + } + } + + if(pbutton->state != BN_PRESSED && pbutton->state != BN_CLICKED) + { + pbutton->state = BN_HOVER; + } + } + else if(event->type != SDL_KEYDOWN && event->type != SDL_KEYUP) + { + pbutton->state = -1; + if(pbutton->show_info) + { + pbutton->show_info = NO; + } + } + + if(event->type == SDL_KEYDOWN) + { + if(key == pbutton->shortcut) + pbutton->state = BN_PRESSED; + } + else if(event->type == SDL_KEYUP) + { + if(pbutton->state == BN_PRESSED && key == pbutton->shortcut) + pbutton->state = BN_CLICKED; + } + else if(event->type == SDL_MOUSEMOTION) + { + + if(pbutton->show_info) + { + pbutton->show_info = NO; + } + } +} + +int button_get_state(button_type* pbutton) +{ + int state; + if(pbutton->state == BN_CLICKED) + { + state = pbutton->state; + pbutton->state = -1; + return state; + } + else + { + return pbutton->state; + } +} + +void button_panel_init(button_panel_type* pbutton_panel, int x, int y, int w, int h) +{ + pbutton_panel->num_items = 0; + pbutton_panel->item = NULL; + pbutton_panel->x = x; + pbutton_panel->y = y; + pbutton_panel->w = w; + pbutton_panel->h = h; + pbutton_panel->hidden = NO; +} + +button_type* button_panel_event(button_panel_type* pbutton_panel, SDL_Event* event) +{ + if(pbutton_panel->hidden == NO) + { + int i; + for(i = 0; i < pbutton_panel->num_items; ++i) + { + button_event(&pbutton_panel->item[i],event); + if(pbutton_panel->item[i].state != -1) + return &pbutton_panel->item[i]; + } + return NULL; + } + else + { + return NULL; + } +} + +void button_panel_free(button_panel_type* pbutton_panel) +{ + int i; + for(i = 0; i < pbutton_panel->num_items; ++i) + { + button_free(&pbutton_panel->item[i]); + } + if(pbutton_panel->num_items) + free(pbutton_panel->item); +} + +void button_panel_draw(button_panel_type* pbutton_panel) +{ + if(pbutton_panel->hidden == NO) + { + int i; + fillrect(pbutton_panel->x,pbutton_panel->y,pbutton_panel->w,pbutton_panel->h,100,100,100,200); + for(i = 0; i < pbutton_panel->num_items; ++i) + { + button_draw(&pbutton_panel->item[i]); + } + } +} + +void button_panel_additem(button_panel_type* pbutton_panel, button_type* pbutton, int tag) +{ + int max_cols, row, col; + + ++pbutton_panel->num_items; + pbutton_panel->item = (button_type*) realloc(pbutton_panel->item, sizeof(button_type) * pbutton_panel->num_items); + memcpy(&pbutton_panel->item[pbutton_panel->num_items-1],pbutton,sizeof(button_type)); + free(pbutton); + + /* A button_panel takes control of the buttons it contains and arranges them */ + + max_cols = pbutton_panel->w / 32; + + row = (pbutton_panel->num_items-1) / max_cols; + col = (pbutton_panel->num_items-1) % max_cols; + + pbutton_panel->item[pbutton_panel->num_items-1].x = pbutton_panel->x + col * 32; + pbutton_panel->item[pbutton_panel->num_items-1].y = pbutton_panel->y + row * 32; + pbutton_panel->item[pbutton_panel->num_items-1].tag = tag; + +} + diff --git a/src/collision.c b/src/collision.c deleted file mode 100644 index fbde783cd..000000000 --- a/src/collision.c +++ /dev/null @@ -1,308 +0,0 @@ -// -// C Implementation: collision -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "defines.h" -#include "collision.h" -#include "bitmask.h" -#include "scene.h" - -int rectcollision(base_type* one, base_type* two) -{ - - if (one->x >= two->x - one->width + 1 && - one->x <= two->x + two->width - 1 && - one->y >= two->y - one->height + 1&& - one->y <= two->y + two->height - 1) - { - return YES; - } - else - { - return NO; - } -} - -int rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y) -{ - if (one->x >= two->x - one->width +off_x + 1 && - one->x <= two->x + two->width + off_x - 1 && - one->y >= two->y - one->height + off_y + 1 && - one->y <= two->y + two->height + off_y - 1) - { - return YES; - } - else - { - return NO; - } -} - -int collision_object_map(base_type* pbase) -{ - int v,h,i; - - v = (int)pbase->height / 16; - h = (int)pbase->width / 16; - - if(issolid(pbase->x + 1, pbase->y + 1) || - issolid(pbase->x + pbase->width -1, pbase->y + 1) || - issolid(pbase->x +1, pbase->y + pbase->height -1) || - issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1)) - return YES; - - for(i = 1; i < h; ++i) - { - if(issolid(pbase->x + i*16,pbase->y + 1)) - return YES; - } - - for(i = 1; i < h; ++i) - { - if( issolid(pbase->x + i*16,pbase->y + pbase->height - 1)) - return YES; - } - - for(i = 1; i < v; ++i) - { - if( issolid(pbase->x + 1, pbase->y + i*16)) - return YES; - } - for(i = 1; i < v; ++i) - { - if( issolid(pbase->x + pbase->width - 1, pbase->y + i*16)) - return YES; - } - - return NO; -} - - -int collision_swept_object_map(base_type* old, base_type* current) -{ - int steps; /* Used to speed up the collision tests, by stepping every 16pixels in the path. */ - int h; - float i; - float lpath; /* Holds the longest path, which is either in X or Y direction. */ - float xd,yd; /* Hold the smallest steps in X and Y directions. */ - float temp, xt, yt; /* Temporary variable. */ - - lpath = 0; - xd = 0; - yd = 0; - - if(old->x == current->x && old->y == current->y) - { - return 0; - } - else if(old->x == current->x && old->y != current->y) - { - lpath = current->y - old->y; - if(lpath < 0) - { - yd = -1; - lpath = -lpath; - } - else - { - yd = 1; - } - - h = 1; - xd = 0; - - } - else if(old->x != current->x && old->y == current->y) - { - lpath = current->x - old->x; - if(lpath < 0) - { - xd = -1; - lpath = -lpath; - } - else - { - xd = 1; - } - h = 2; - yd = 0; - } - else - { - lpath = current->x - old->x; - if(lpath < 0) - lpath = -lpath; - if(current->y - old->y > lpath || old->y - current->y > lpath) - lpath = current->y - old->y; - if(lpath < 0) - lpath = -lpath; - h = 3; - xd = (current->x - old->x) / lpath; - yd = (current->y - old->y) / lpath; - } - - steps = (int)(lpath / (float)16); - - old->x += xd; - old->y += yd; - - for(i = 0; i <= lpath; old->x += xd, old->y += yd, ++i) - { - if(steps > 0) - { - old->y += yd*16.; - old->x += xd*16.; - steps--; - } - - if(collision_object_map(old)) - { - switch(h) - { - case 1: - current->y = old->y - yd; - while(collision_object_map(current)) - current->y -= yd; - break; - case 2: - current->x = old->x - xd; - while(collision_object_map(current)) - current->x -= xd; - break; - case 3: - xt = current->x; - yt = current->y; - current->x = old->x - xd; - current->y = old->y - yd; - while(collision_object_map(current)) - { - current->x -= xd; - current->y -= yd; - } - - temp = current->x; - current->x = xt; - if(!collision_object_map(current)) - break; - current->x = temp; - temp = current->y; - current->y = yt; - - if(!collision_object_map(current)) - { - break; - } - else - { - current->y = temp; - while(!collision_object_map(current)) - current->y += yd; - current->y -= yd; - break; - } - - break; - default: - break; - } - break; - } - } - - *old = *current; - -} - -void collision_handler() -{ - int i,j; - - /* CO_BULLET & CO_BADGUY check */ - for(i = 0; i < num_bullets; ++i) - { - if(bullets[i].base.alive) - { - for(j = 0; j < num_bad_guys; ++j) - { - if(bad_guys[j].dying == NO && bad_guys[j].base.alive) - { - if(rectcollision(&bullets[i].base,&bad_guys[j].base) == YES) - { - /* We have detected a collision and now call the collision functions of the collided objects. */ - bullet_collision(&bullets[i], CO_BADGUY); - badguy_collision(&bad_guys[j], &bullets[i], CO_BULLET); - } - } - } - } - } - - /* CO_BADGUY & CO_BADGUY check */ - for(i = 0; i < num_bad_guys; ++i) - { - if(bad_guys[i].base.alive && bad_guys[i].dying == NO) - { - for(j = i+1; j < num_bad_guys; ++j) - { - if(j != i && bad_guys[j].base.alive && bad_guys[j].dying == NO) - { - if(rectcollision(&bad_guys[i].base,&bad_guys[j].base) == YES) - { - /* We have detected a collision and now call the collision functions of the collided objects. */ - badguy_collision(&bad_guys[j], &bad_guys[i], CO_BADGUY); - badguy_collision(&bad_guys[i], &bad_guys[j], CO_BADGUY); - } - } - } - } - } - - - - /* CO_BADGUY & CO_PLAYER check */ - for(i = 0; i < num_bad_guys; ++i) - { - if(bad_guys[i].base.alive) - { - if(bad_guys[i].dying == NO && rectcollision_offset(&bad_guys[i].base,&tux.base,0,0) == YES ) - { - /* We have detected a collision and now call the collision functions of the collided objects. */ - if (tux.previous_base.y < tux.base.y && - tux.previous_base.y + tux.previous_base.height < bad_guys[i].base.y + bad_guys[i].base.height/2 && - bad_guys[i].kind != BAD_MONEY && bad_guys[i].mode != HELD) - { - badguy_collision(&bad_guys[i], &tux, CO_PLAYER); - } - else - { - player_collision(&tux, &bad_guys[i], CO_BADGUY); - } - } - } - } - - /* CO_UPGRADE & CO_PLAYER check */ - for(i = 0; i < num_upgrades; ++i) - { - if(upgrades[i].base.alive) - { - if(rectcollision(&upgrades[i].base,&tux.base) == YES) - { - /* We have detected a collision and now call the collision functions of the collided objects. */ - upgrade_collision(&upgrades[i], &tux, CO_PLAYER); - } - - } - } - -} - - diff --git a/src/collision.cpp b/src/collision.cpp new file mode 100644 index 000000000..fbde783cd --- /dev/null +++ b/src/collision.cpp @@ -0,0 +1,308 @@ +// +// C Implementation: collision +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "defines.h" +#include "collision.h" +#include "bitmask.h" +#include "scene.h" + +int rectcollision(base_type* one, base_type* two) +{ + + if (one->x >= two->x - one->width + 1 && + one->x <= two->x + two->width - 1 && + one->y >= two->y - one->height + 1&& + one->y <= two->y + two->height - 1) + { + return YES; + } + else + { + return NO; + } +} + +int rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y) +{ + if (one->x >= two->x - one->width +off_x + 1 && + one->x <= two->x + two->width + off_x - 1 && + one->y >= two->y - one->height + off_y + 1 && + one->y <= two->y + two->height + off_y - 1) + { + return YES; + } + else + { + return NO; + } +} + +int collision_object_map(base_type* pbase) +{ + int v,h,i; + + v = (int)pbase->height / 16; + h = (int)pbase->width / 16; + + if(issolid(pbase->x + 1, pbase->y + 1) || + issolid(pbase->x + pbase->width -1, pbase->y + 1) || + issolid(pbase->x +1, pbase->y + pbase->height -1) || + issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1)) + return YES; + + for(i = 1; i < h; ++i) + { + if(issolid(pbase->x + i*16,pbase->y + 1)) + return YES; + } + + for(i = 1; i < h; ++i) + { + if( issolid(pbase->x + i*16,pbase->y + pbase->height - 1)) + return YES; + } + + for(i = 1; i < v; ++i) + { + if( issolid(pbase->x + 1, pbase->y + i*16)) + return YES; + } + for(i = 1; i < v; ++i) + { + if( issolid(pbase->x + pbase->width - 1, pbase->y + i*16)) + return YES; + } + + return NO; +} + + +int collision_swept_object_map(base_type* old, base_type* current) +{ + int steps; /* Used to speed up the collision tests, by stepping every 16pixels in the path. */ + int h; + float i; + float lpath; /* Holds the longest path, which is either in X or Y direction. */ + float xd,yd; /* Hold the smallest steps in X and Y directions. */ + float temp, xt, yt; /* Temporary variable. */ + + lpath = 0; + xd = 0; + yd = 0; + + if(old->x == current->x && old->y == current->y) + { + return 0; + } + else if(old->x == current->x && old->y != current->y) + { + lpath = current->y - old->y; + if(lpath < 0) + { + yd = -1; + lpath = -lpath; + } + else + { + yd = 1; + } + + h = 1; + xd = 0; + + } + else if(old->x != current->x && old->y == current->y) + { + lpath = current->x - old->x; + if(lpath < 0) + { + xd = -1; + lpath = -lpath; + } + else + { + xd = 1; + } + h = 2; + yd = 0; + } + else + { + lpath = current->x - old->x; + if(lpath < 0) + lpath = -lpath; + if(current->y - old->y > lpath || old->y - current->y > lpath) + lpath = current->y - old->y; + if(lpath < 0) + lpath = -lpath; + h = 3; + xd = (current->x - old->x) / lpath; + yd = (current->y - old->y) / lpath; + } + + steps = (int)(lpath / (float)16); + + old->x += xd; + old->y += yd; + + for(i = 0; i <= lpath; old->x += xd, old->y += yd, ++i) + { + if(steps > 0) + { + old->y += yd*16.; + old->x += xd*16.; + steps--; + } + + if(collision_object_map(old)) + { + switch(h) + { + case 1: + current->y = old->y - yd; + while(collision_object_map(current)) + current->y -= yd; + break; + case 2: + current->x = old->x - xd; + while(collision_object_map(current)) + current->x -= xd; + break; + case 3: + xt = current->x; + yt = current->y; + current->x = old->x - xd; + current->y = old->y - yd; + while(collision_object_map(current)) + { + current->x -= xd; + current->y -= yd; + } + + temp = current->x; + current->x = xt; + if(!collision_object_map(current)) + break; + current->x = temp; + temp = current->y; + current->y = yt; + + if(!collision_object_map(current)) + { + break; + } + else + { + current->y = temp; + while(!collision_object_map(current)) + current->y += yd; + current->y -= yd; + break; + } + + break; + default: + break; + } + break; + } + } + + *old = *current; + +} + +void collision_handler() +{ + int i,j; + + /* CO_BULLET & CO_BADGUY check */ + for(i = 0; i < num_bullets; ++i) + { + if(bullets[i].base.alive) + { + for(j = 0; j < num_bad_guys; ++j) + { + if(bad_guys[j].dying == NO && bad_guys[j].base.alive) + { + if(rectcollision(&bullets[i].base,&bad_guys[j].base) == YES) + { + /* We have detected a collision and now call the collision functions of the collided objects. */ + bullet_collision(&bullets[i], CO_BADGUY); + badguy_collision(&bad_guys[j], &bullets[i], CO_BULLET); + } + } + } + } + } + + /* CO_BADGUY & CO_BADGUY check */ + for(i = 0; i < num_bad_guys; ++i) + { + if(bad_guys[i].base.alive && bad_guys[i].dying == NO) + { + for(j = i+1; j < num_bad_guys; ++j) + { + if(j != i && bad_guys[j].base.alive && bad_guys[j].dying == NO) + { + if(rectcollision(&bad_guys[i].base,&bad_guys[j].base) == YES) + { + /* We have detected a collision and now call the collision functions of the collided objects. */ + badguy_collision(&bad_guys[j], &bad_guys[i], CO_BADGUY); + badguy_collision(&bad_guys[i], &bad_guys[j], CO_BADGUY); + } + } + } + } + } + + + + /* CO_BADGUY & CO_PLAYER check */ + for(i = 0; i < num_bad_guys; ++i) + { + if(bad_guys[i].base.alive) + { + if(bad_guys[i].dying == NO && rectcollision_offset(&bad_guys[i].base,&tux.base,0,0) == YES ) + { + /* We have detected a collision and now call the collision functions of the collided objects. */ + if (tux.previous_base.y < tux.base.y && + tux.previous_base.y + tux.previous_base.height < bad_guys[i].base.y + bad_guys[i].base.height/2 && + bad_guys[i].kind != BAD_MONEY && bad_guys[i].mode != HELD) + { + badguy_collision(&bad_guys[i], &tux, CO_PLAYER); + } + else + { + player_collision(&tux, &bad_guys[i], CO_BADGUY); + } + } + } + } + + /* CO_UPGRADE & CO_PLAYER check */ + for(i = 0; i < num_upgrades; ++i) + { + if(upgrades[i].base.alive) + { + if(rectcollision(&upgrades[i].base,&tux.base) == YES) + { + /* We have detected a collision and now call the collision functions of the collided objects. */ + upgrade_collision(&upgrades[i], &tux, CO_PLAYER); + } + + } + } + +} + + diff --git a/src/gameloop.c b/src/gameloop.c deleted file mode 100644 index 5a39f066e..000000000 --- a/src/gameloop.c +++ /dev/null @@ -1,1807 +0,0 @@ -/* - gameloop.c - - Super Tux - Game Loop! - - by Bill Kendrick & Tobias Glaesser - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 11, 2000 - March 15, 2004 - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef LINUX -#include -#include -#include -#endif - -#include "defines.h" -#include "globals.h" -#include "gameloop.h" -#include "screen.h" -#include "setup.h" -#include "high_scores.h" -#include "menu.h" -#include "badguy.h" -#include "world.h" -#include "special.h" -#include "player.h" -#include "level.h" -#include "scene.h" -#include "collision.h" - -/* extern variables */ - -st_level current_level; -int game_started = NO; - -/* Local variables: */ - -static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2]; -static texture_type img_cloud[2][4]; -static SDL_Event event; -static SDLKey key; -static char level_subset[100]; -static char str[60]; -static float fps_fps; -static int st_gl_mode; -static unsigned int last_update_time; -static unsigned int update_time; -static int pause_menu_frame; -static int debug_fps; - -/* Local function prototypes: */ - -void levelintro(void); -void loadshared(void); -void unloadshared(void); -void drawstatus(void); -void drawendscreen(void); -void drawresultscreen(void); - -#define JOYSTICK_DEAD_ZONE 4096 - -void levelintro(void) -{ - /* Level Intro: */ - - clearscreen(0, 0, 0); - - sprintf(str, "LEVEL %d", level); - text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - sprintf(str, "%s", current_level.name); - text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - sprintf(str, "TUX x %d", tux.lives); - text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - flipscreen(); - - SDL_Delay(1000); -} - -/* Reset Timers */ -void start_timers(void) -{ - timer_start(&time_left,current_level.time_left*1000); - st_pause_ticks_init(); - update_time = st_get_ticks(); -} - -void activate_bad_guys(void) -{ - int x,y; - - /* Activate bad guys: */ - - for (y = 0; y < 15; y++) - { - for (x = 0; x < current_level.width; x++) - { - if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9') - { - add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0'); - current_level.tiles[y][x] = '.'; - } - } - } - -} - -/* --- GAME EVENT! --- */ - -void game_event(void) -{ - while (SDL_PollEvent(&event)) - { - switch(event.type) - { - case SDL_QUIT: /* Quit event - quit: */ - quit = 1; - break; - case SDL_KEYDOWN: /* A keypress! */ - key = event.key.keysym.sym; - - /* Check for menu-events, if the menu is shown */ - if(show_menu) - menu_event(&event.key.keysym); - - if(player_key_event(&tux,key,DOWN)) - break; - - switch(key) - { - case SDLK_ESCAPE: /* Escape: Open/Close the menu: */ - if(!game_pause) - { - if(st_gl_mode == ST_GL_TEST) - quit = 1; - else if(show_menu) - { - menu_set_current(&game_menu); - show_menu = 0; - st_pause_ticks_stop(); - } - else - { - menu_set_current(&game_menu); - show_menu = 1; - st_pause_ticks_start(); - } - } - break; - default: - break; - } - break; - case SDL_KEYUP: /* A keyrelease! */ - key = event.key.keysym.sym; - - if(player_key_event(&tux,key,UP)) - break; - - switch(key) - { - case SDLK_p: - if(!show_menu) - { - if(game_pause) - { - game_pause = 0; - st_pause_ticks_stop(); - } - else - { - game_pause = 1; - st_pause_ticks_start(); - } - } - break; - case SDLK_TAB: - if(debug_mode == YES) - { - tux.size = !tux.size; - if(tux.size == BIG) - { - tux.base.height = 64; - } - else - tux.base.height = 32; - } - break; - case SDLK_END: - if(debug_mode == YES) - distros += 50; - break; - case SDLK_SPACE: - if(debug_mode == YES) - next_level = 1; - break; - case SDLK_DELETE: - if(debug_mode == YES) - tux.got_coffee = 1; - break; - case SDLK_INSERT: - if(debug_mode == YES) - timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME); - break; - case SDLK_l: - if(debug_mode == YES) - --tux.lives; - break; - case SDLK_s: - if(debug_mode == YES) - score += 1000; - case SDLK_f: - if(debug_fps == YES) - debug_fps = NO; - else - debug_fps = YES; - break; - default: - break; - } - break; -#ifdef JOY_YES - - case SDL_JOYAXISMOTION: - switch(event.jaxis.axis) - { - case JOY_X: - if (event.jaxis.value < -JOYSTICK_DEAD_ZONE) - tux.input.left = DOWN; - else if (event.jaxis.value > JOYSTICK_DEAD_ZONE) - tux.input.left = UP; - - if (event.jaxis.value > JOYSTICK_DEAD_ZONE) - tux.input.right = DOWN; - else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE) - tux.input.right = UP; - break; - case JOY_Y: - if (event.jaxis.value > JOYSTICK_DEAD_ZONE) - tux.input.down = DOWN; - else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE) - tux.input.down = UP; - - /* Handle joystick for the menu */ - if(show_menu) - { - if(tux.input.down == DOWN) - menuaction = MN_DOWN; - else - menuaction = MN_UP; - } - break; - default: - break; - } - break; - case SDL_JOYBUTTONDOWN: - if (event.jbutton.button == JOY_A) - tux.input.up = DOWN; - else if (event.jbutton.button == JOY_B) - tux.input.fire = DOWN; - break; - case SDL_JOYBUTTONUP: - if (event.jbutton.button == JOY_A) - tux.input.up = UP; - else if (event.jbutton.button == JOY_B) - tux.input.fire = UP; - - if(show_menu) - menuaction = MN_HIT; - break; - -#endif - default: - break; - - } /* switch */ - - } /* while */ - -} - -/* --- GAME ACTION! --- */ - -int game_action(void) -{ - int i; - - /* (tux_dying || next_level) */ - if (tux.dying || next_level) - { - /* Tux either died, or reached the end of a level! */ - - halt_music(); - - - if (next_level) - { - /* End of a level! */ - level++; - next_level = 0; - if(st_gl_mode != ST_GL_TEST) - { - drawresultscreen(); - } - else - { - level_free_gfx(); - level_free(¤t_level); - level_free_song(); - unloadshared(); - arrays_free(); - return(0); - } - player_level_begin(&tux); - } - else - { - player_dying(&tux); - - /* No more lives!? */ - - if (tux.lives < 0) - { - if(st_gl_mode != ST_GL_TEST) - drawendscreen(); - - if(st_gl_mode != ST_GL_TEST) - { - if (score > hs_score) - save_hs(score); - } - level_free_gfx(); - level_free(¤t_level); - level_free_song(); - unloadshared(); - arrays_free(); - return(0); - } /* if (lives < 0) */ - } - - /* Either way, (re-)load the (next) level... */ - - player_level_begin(&tux); - set_defaults(); - level_free(¤t_level); - if(level_load(¤t_level,level_subset,level) != 0) - return 0; - arrays_free(); - arrays_init(); - activate_bad_guys(); - level_free_gfx(); - level_load_gfx(¤t_level); - level_free_song(); - level_load_song(¤t_level); - if(st_gl_mode != ST_GL_TEST) - levelintro(); - start_timers(); - /* Play music: */ - play_current_music(); - } - - player_action(&tux); - - /* Handle bouncy distros: */ - - for (i = 0; i < num_bouncy_distros; i++) - { - bouncy_distro_action(&bouncy_distros[i]); - } - - - /* Handle broken bricks: */ - - for (i = 0; i < num_broken_bricks; i++) - { - broken_brick_action(&broken_bricks[i]); - } - - - /* Handle distro counting: */ - - if (counting_distros == YES) - { - distro_counter--; - - if (distro_counter <= 0) - counting_distros = -1; - } - - - /* Handle bouncy bricks: */ - - for (i = 0; i < num_bouncy_bricks; i++) - { - bouncy_brick_action(&bouncy_bricks[i]); - } - - - /* Handle floating scores: */ - - for (i = 0; i < num_floating_scores; i++) - { - floating_score_action(&floating_scores[i]); - } - - - /* Handle bullets: */ - - for (i = 0; i < num_bullets; ++i) - { - bullet_action(&bullets[i]); - } - - /* Handle upgrades: */ - - for (i = 0; i < num_upgrades; i++) - { - upgrade_action(&upgrades[i]); - } - - - /* Handle bad guys: */ - - for (i = 0; i < num_bad_guys; i++) - { - badguy_action(&bad_guys[i]); - } - - /* Handle all possible collisions. */ - collision_handler(); - - return -1; -} - -/* --- GAME DRAW! --- */ - -void game_draw(void) -{ - int x, y, i, s; - - /* Draw screen: */ - - if (tux.dying && (frame % 4) == 0) - clearscreen(255, 255, 255); - else if(timer_check(&super_bkgd_timer)) - texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE); - else - { - /* Draw the real background */ - if(current_level.bkgd_image[0] != '\0') - { - s = (int)scroll_x / 30; - texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE); - texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE); - } - else - { - clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); - } - } - - /* Draw background: */ - - for (y = 0; y < 15; ++y) - { - for (x = 0; x < 21; ++x) - { - drawshape(x * 32 - ((int)scroll_x % 32), y * 32, - current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]); - } - } - - - /* (Bouncy bricks): */ - - for (i = 0; i < num_bouncy_bricks; ++i) - { - bouncy_brick_draw(&bouncy_bricks[i]); - } - - - /* (Bad guys): */ - - for (i = 0; i < num_bad_guys; ++i) - { - badguy_draw(&bad_guys[i]); - } - - /* (Tux): */ - - player_draw(&tux); - - /* (Bullets): */ - - for (i = 0; i < num_bullets; ++i) - { - bullet_draw(&bullets[i]); - } - - /* (Floating scores): */ - - for (i = 0; i < num_floating_scores; ++i) - { - floating_score_draw(&floating_scores[i]); - } - - - /* (Upgrades): */ - - for (i = 0; i < num_upgrades; ++i) - { - upgrade_draw(&upgrades[i]); - } - - - /* (Bouncy distros): */ - - for (i = 0; i < num_bouncy_distros; ++i) - { - bouncy_distro_draw(&bouncy_distros[i]); - } - - - /* (Broken bricks): */ - - for (i = 0; i < num_broken_bricks; ++i) - { - broken_brick_draw(&broken_bricks[i]); - } - - drawstatus(); - - - if(game_pause) - { - x = screen->h / 20; - for(i = 0; i < x; ++i) - { - fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1); - } - fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128); - text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - } - - if(show_menu) - menu_process_current(); - - /* (Update it all!) */ - - updatescreen(); - - -} - -/* --- GAME LOOP! --- */ - -int gameloop(char * subset, int levelnb, int mode) -{ - int fps_cnt, jump, done; - timer_type fps_timer, frame_timer; - timer_init(&fps_timer, YES); - timer_init(&frame_timer, YES); - - game_started = YES; - - st_gl_mode = mode; - level = levelnb; - strcpy(level_subset,subset); - - /* Init the game: */ - arrays_init(); - set_defaults(); - - if(level_load(¤t_level,level_subset,level) != 0) - exit(1); - level_load_gfx(¤t_level); - activate_bad_guys(); - level_load_song(¤t_level); - - player_init(&tux); - - if(st_gl_mode != ST_GL_TEST) - load_hs(); - - loadshared(); - - if(st_gl_mode == ST_GL_PLAY) - levelintro(); - - - timer_init(&time_left,YES); - start_timers(); - - if(st_gl_mode == ST_GL_LOAD_GAME) - loadgame(levelnb); - - - /* --- MAIN GAME LOOP!!! --- */ - - jump = NO; - done = 0; - quit = 0; - frame = 0; - game_pause = 0; - timer_init(&fps_timer,YES); - timer_init(&frame_timer,YES); - fps_cnt = 0; - - /* Clear screen: */ - - clearscreen(0, 0, 0); - updatescreen(); - - /* Play music: */ - play_current_music(); - - - while (SDL_PollEvent(&event)) - {} - - game_draw(); - do - { - jump = NO; - - /* Calculate the movement-factor */ - frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE); - if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */ - frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85; - - if(!timer_check(&frame_timer)) - { - timer_start(&frame_timer,25); - ++frame; - } - - /* Handle events: */ - - tux.input.old_fire = tux.input.fire; - - game_event(); - - if(show_menu) - { - if(current_menu == &game_menu) - { - switch (menu_check(&game_menu)) - { - case 2: - st_pause_ticks_stop(); - break; - case 3: - update_load_save_game_menu(&save_game_menu, NO); - break; - case 4: - update_load_save_game_menu(&load_game_menu, YES); - break; - case 7: - st_pause_ticks_stop(); - done = 1; - break; - } - } - else if(current_menu == &options_menu) - { - process_options_menu(); - } - else if(current_menu == &save_game_menu ) - { - process_save_load_game_menu(YES); - } - else if(current_menu == &load_game_menu ) - { - process_save_load_game_menu(NO); - } - } - - - /* Handle actions: */ - - if(!game_pause && !show_menu) - { - /*float z = frame_ratio; - frame_ratio = 1; - while(z >= 1) - {*/ - if (game_action() == 0) - { - /* == 0: no more lives */ - /* == -1: continues */ - return 0; - } - /* --z; - }*/ - } - else - { - ++pause_menu_frame; - SDL_Delay(50); - } - - if(debug_mode && debug_fps == YES) - SDL_Delay(60); - - /*Draw the current scene to the screen */ - /*If the machine running the game is too slow - skip the drawing of the frame (so the calculations are more precise and - the FPS aren't affected).*/ - /*if( ! fps_fps < 50.0 ) - game_draw(); - else - jump = YES;*/ /*FIXME: Implement this tweak right.*/ - game_draw(); - - /* Time stops in pause mode */ - if(game_pause || show_menu ) - { - continue; - } - - /* Set the time of the last update and the time of the current update */ - last_update_time = update_time; - update_time = st_get_ticks(); - - - /* Pause till next frame, if the machine running the game is too fast: */ - /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But - the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */ - if(last_update_time >= update_time - 12 && jump != YES ) - SDL_Delay(10); - /*if((update_time - last_update_time) < 10) - SDL_Delay((11 - (update_time - last_update_time))/2);*/ - - - - /* Handle time: */ - - if (timer_check(&time_left)) - { - /* are we low on time ? */ - if ((timer_get_left(&time_left) < TIME_WARNING) - && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */ - { - set_current_music(HURRYUP_MUSIC); - play_current_music(); - } - - } - else - player_kill(&tux,KILL); - - - /* Calculate frames per second */ - if(show_fps) - { - ++fps_cnt; - fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt; - - if(!timer_check(&fps_timer)) - { - timer_start(&fps_timer,1000); - fps_cnt = 0; - } - } - - } - while (!done && !quit); - - halt_music(); - - level_free_gfx(); - level_free(¤t_level); - level_free_song(); - unloadshared(); - arrays_free(); - - game_started = NO; - - return(quit); -} - - -/* Load graphics/sounds shared between all levels: */ - -void loadshared(void) -{ - int i; - char * herring_song_path; /* for loading herring song*/ - - /* Tuxes: */ - - texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA); - texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA); - texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA); - - texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA); - texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA); - texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA); - - texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA); - texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA); - texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA); - - texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA); - texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA); - texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA); - - - texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png", - USE_ALPHA); - - texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png", - USE_ALPHA); - - texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png", - USE_ALPHA); - - texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png", - USE_ALPHA); - - texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png", - USE_ALPHA); - - texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png", - USE_ALPHA); - - texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png", - USE_ALPHA); - - texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA); - - texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png", - USE_ALPHA); - - texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png", - USE_ALPHA); - - texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png", - USE_ALPHA); - - texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA); - - texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png", - USE_ALPHA); - - texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png", - USE_ALPHA); - - texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png", - USE_ALPHA); - - texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png", - USE_ALPHA); - - texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png", - USE_ALPHA); - - texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png", - USE_ALPHA); - - texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png", - USE_ALPHA); - - texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA); - - texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png", - USE_ALPHA); - - texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png", - USE_ALPHA); - - texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png", - USE_ALPHA); - - texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA); - - texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png", - USE_ALPHA); - - texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png", - USE_ALPHA); - - texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png", - USE_ALPHA); - - texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png", - USE_ALPHA); - - - texture_load(&ducktux_right ,DATA_PREFIX - "/images/shared/ducktux-right.png", - USE_ALPHA); - - texture_load(&ducktux_left ,DATA_PREFIX - "/images/shared/ducktux-left.png", - USE_ALPHA); - - texture_load(&skidtux_right ,DATA_PREFIX - "/images/shared/skidtux-right.png", - USE_ALPHA); - - texture_load(&skidtux_left ,DATA_PREFIX - "/images/shared/skidtux-left.png", - USE_ALPHA); - - texture_load(&duckfiretux_right ,DATA_PREFIX - "/images/shared/duckfiretux-right.png", - USE_ALPHA); - - texture_load(&duckfiretux_left ,DATA_PREFIX - "/images/shared/duckfiretux-left.png", - USE_ALPHA); - - texture_load(&skidfiretux_right ,DATA_PREFIX - "/images/shared/skidfiretux-right.png", - USE_ALPHA); - - texture_load(&skidfiretux_left ,DATA_PREFIX - "/images/shared/skidfiretux-left.png", - USE_ALPHA); - - - /* Boxes: */ - - texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png", - IGNORE_ALPHA); - texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png", - IGNORE_ALPHA); - - - /* Water: */ - - - texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA); - - texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png", - USE_ALPHA); - - texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png", - USE_ALPHA); - - texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png", - USE_ALPHA); - - - /* Pole: */ - - texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA); - texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png", - USE_ALPHA); - - - /* Flag: */ - - texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png", - USE_ALPHA); - texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png", - USE_ALPHA); - - - /* Cloud: */ - - texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png", - USE_ALPHA); - - texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png", - USE_ALPHA); - - texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png", - USE_ALPHA); - - texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png", - USE_ALPHA); - - - texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png", - USE_ALPHA); - - texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png", - USE_ALPHA); - - texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png", - USE_ALPHA); - - texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png", - USE_ALPHA); - - - /* Bad guys: */ - - /* (BSOD) */ - - texture_load(&img_bsod_left[0] ,DATA_PREFIX - "/images/shared/bsod-left-0.png", - USE_ALPHA); - - texture_load(&img_bsod_left[1] ,DATA_PREFIX - "/images/shared/bsod-left-1.png", - USE_ALPHA); - - texture_load(&img_bsod_left[2] ,DATA_PREFIX - "/images/shared/bsod-left-2.png", - USE_ALPHA); - - texture_load(&img_bsod_left[3] ,DATA_PREFIX - "/images/shared/bsod-left-3.png", - USE_ALPHA); - - texture_load(&img_bsod_right[0] ,DATA_PREFIX - "/images/shared/bsod-right-0.png", - USE_ALPHA); - - texture_load(&img_bsod_right[1] ,DATA_PREFIX - "/images/shared/bsod-right-1.png", - USE_ALPHA); - - texture_load(&img_bsod_right[2] ,DATA_PREFIX - "/images/shared/bsod-right-2.png", - USE_ALPHA); - - texture_load(&img_bsod_right[3] ,DATA_PREFIX - "/images/shared/bsod-right-3.png", - USE_ALPHA); - - texture_load(&img_bsod_squished_left ,DATA_PREFIX - "/images/shared/bsod-squished-left.png", - USE_ALPHA); - - texture_load(&img_bsod_squished_right ,DATA_PREFIX - "/images/shared/bsod-squished-right.png", - USE_ALPHA); - - texture_load(&img_bsod_falling_left ,DATA_PREFIX - "/images/shared/bsod-falling-left.png", - USE_ALPHA); - - texture_load(&img_bsod_falling_right ,DATA_PREFIX - "/images/shared/bsod-falling-right.png", - USE_ALPHA); - - - /* (Laptop) */ - - texture_load(&img_laptop_left[0] ,DATA_PREFIX - "/images/shared/laptop-left-0.png", - USE_ALPHA); - - texture_load(&img_laptop_left[1] ,DATA_PREFIX - "/images/shared/laptop-left-1.png", - USE_ALPHA); - - texture_load(&img_laptop_left[2] ,DATA_PREFIX - "/images/shared/laptop-left-2.png", - USE_ALPHA); - - texture_load(&img_laptop_right[0] ,DATA_PREFIX - "/images/shared/laptop-right-0.png", - USE_ALPHA); - - texture_load(&img_laptop_right[1] ,DATA_PREFIX - "/images/shared/laptop-right-1.png", - USE_ALPHA); - - texture_load(&img_laptop_right[2] ,DATA_PREFIX - "/images/shared/laptop-right-2.png", - USE_ALPHA); - - texture_load(&img_laptop_flat_left ,DATA_PREFIX - "/images/shared/laptop-flat-left.png", - USE_ALPHA); - - texture_load(&img_laptop_flat_right ,DATA_PREFIX - "/images/shared/laptop-flat-right.png", - USE_ALPHA); - - texture_load(&img_laptop_falling_left ,DATA_PREFIX - "/images/shared/laptop-falling-left.png", - USE_ALPHA); - - texture_load(&img_laptop_falling_right ,DATA_PREFIX - "/images/shared/laptop-falling-right.png", - USE_ALPHA); - - - /* (Money) */ - - texture_load(&img_money_left[0] ,DATA_PREFIX - "/images/shared/bag-left-0.png", - USE_ALPHA); - - texture_load(&img_money_left[1] ,DATA_PREFIX - "/images/shared/bag-left-1.png", - USE_ALPHA); - - texture_load(&img_money_right[0] ,DATA_PREFIX - "/images/shared/bag-right-0.png", - USE_ALPHA); - - texture_load(&img_money_right[1] ,DATA_PREFIX - "/images/shared/bag-right-1.png", - USE_ALPHA); - - - - /* Upgrades: */ - - texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA); - texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA); - - - /* Weapons: */ - - texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA); - - texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png", - USE_ALPHA); - - - - /* Distros: */ - - texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png", - USE_ALPHA); - - texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png", - USE_ALPHA); - - texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png", - USE_ALPHA); - - texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png", - USE_ALPHA); - - - /* Tux life: */ - - texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png", - USE_ALPHA); - - /* Herring: */ - - texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png", - USE_ALPHA); - - - /* Super background: */ - - texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png", - IGNORE_ALPHA); - - - /* Sound effects: */ - - /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound" - // initialize sounds[i] with the correct pointer's value: - // NULL or something else. And it will be dangerous to - // play with not-initialized pointers. - // This is also true with if (use_music) - Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :) - */ - for (i = 0; i < NUM_SOUNDS; i++) - sounds[i] = load_sound(soundfilenames[i]); - - /* Herring song */ - herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + - strlen("SALCON.MOD") + 8)); - - sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD"); - - herring_song = load_song(herring_song_path); - - free(herring_song_path); - -} - - -/* Free shared data: */ - -void unloadshared(void) -{ - int i; - - for (i = 0; i < 3; i++) - { - texture_free(&tux_right[i]); - texture_free(&tux_left[i]); - texture_free(&bigtux_right[i]); - texture_free(&bigtux_left[i]); - } - - texture_free(&bigtux_right_jump); - texture_free(&bigtux_left_jump); - - for (i = 0; i < 2; i++) - { - texture_free(&cape_right[i]); - texture_free(&cape_left[i]); - texture_free(&bigcape_right[i]); - texture_free(&bigcape_left[i]); - } - - texture_free(&ducktux_left); - texture_free(&ducktux_right); - - texture_free(&skidtux_left); - texture_free(&skidtux_right); - - for (i = 0; i < 4; i++) - { - texture_free(&img_bsod_left[i]); - texture_free(&img_bsod_right[i]); - } - - texture_free(&img_bsod_squished_left); - texture_free(&img_bsod_squished_right); - - texture_free(&img_bsod_falling_left); - texture_free(&img_bsod_falling_right); - - for (i = 0; i < 3; i++) - { - texture_free(&img_laptop_left[i]); - texture_free(&img_laptop_right[i]); - } - - texture_free(&img_laptop_flat_left); - texture_free(&img_laptop_flat_right); - - texture_free(&img_laptop_falling_left); - texture_free(&img_laptop_falling_right); - - for (i = 0; i < 2; i++) - { - texture_free(&img_money_left[i]); - texture_free(&img_money_right[i]); - } - - texture_free(&img_box_full); - texture_free(&img_box_empty); - - texture_free(&img_water); - for (i = 0; i < 3; i++) - texture_free(&img_waves[i]); - - texture_free(&img_pole); - texture_free(&img_poletop); - - for (i = 0; i < 2; i++) - texture_free(&img_flag[i]); - - texture_free(&img_mints); - texture_free(&img_coffee); - - for (i = 0; i < 4; i++) - { - texture_free(&img_distro[i]); - texture_free(&img_cloud[0][i]); - texture_free(&img_cloud[1][i]); - } - - texture_free(&img_golden_herring); - - for (i = 0; i < NUM_SOUNDS; i++) - free_chunk(sounds[i]); - - /* free the herring song */ - free_music( herring_song ); -} - - -/* Draw a tile on the screen: */ - -void drawshape(float x, float y, unsigned char c) -{ - int z; - - if (c == 'X' || c == 'x') - texture_draw(&img_brick[0], x, y, NO_UPDATE); - else if (c == 'Y' || c == 'y') - texture_draw(&img_brick[1], x, y, NO_UPDATE); - else if (c == 'A' || c =='B' || c == '!') - texture_draw(&img_box_full, x, y, NO_UPDATE); - else if (c == 'a') - texture_draw(&img_box_empty, x, y, NO_UPDATE); - else if (c >= 'C' && c <= 'F') - texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE); - else if (c >= 'c' && c <= 'f') - texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE); - else if (c >= 'G' && c <= 'J') - texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE); - else if (c >= 'g' && c <= 'j') - texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE); - else if (c == '#') - texture_draw(&img_solid[0], x, y, NO_UPDATE); - else if (c == '[') - texture_draw(&img_solid[1], x, y, NO_UPDATE); - else if (c == '=') - texture_draw(&img_solid[2], x, y, NO_UPDATE); - else if (c == ']') - texture_draw(&img_solid[3], x, y, NO_UPDATE); - else if (c == '$') - { - - z = (frame / 2) % 6; - - if (z < 4) - texture_draw(&img_distro[z], x, y, NO_UPDATE); - else if (z == 4) - texture_draw(&img_distro[2], x, y, NO_UPDATE); - else if (z == 5) - texture_draw(&img_distro[1], x, y, NO_UPDATE); - } - else if (c == '^') - { - z = (frame / 3) % 3; - - texture_draw(&img_waves[z], x, y, NO_UPDATE); - } - else if (c == '*') - texture_draw(&img_poletop, x, y, NO_UPDATE); - else if (c == '|') - { - texture_draw(&img_pole, x, y, NO_UPDATE); - - } - else if (c == '\\') - { - z = (frame / 3) % 2; - - texture_draw(&img_flag[z], x + 16, y, NO_UPDATE); - } - else if (c == '&') - texture_draw(&img_water, x, y, NO_UPDATE); -} - - -/* What shape is at some position? */ - -unsigned char shape(float x, float y) -{ - - int xx, yy; - unsigned char c; - - yy = ((int)y / 32); - xx = ((int)x / 32); - - if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width) - { - c = current_level.tiles[yy][xx]; - } - else - c = '.'; - - return(c); -} - -/* Is is ground? */ - - -int issolid(float x, float y) -{ - if (isbrick(x, y) || - isice(x, y) || - (shape(x, y) == '[') || - (shape(x, y) == '=') || - (shape(x, y) == ']') || - (shape(x, y) == 'A') || - (shape(x, y) == 'B') || - (shape(x, y) == '!') || - (shape(x, y) == 'a')) - { - return YES; - } - - return NO; -} - - -/* Is it a brick? */ - -int isbrick(float x, float y) -{ - if (shape(x, y) == 'X' || - shape(x, y) == 'x' || - shape(x, y) == 'Y' || - shape(x, y) == 'y') - { - return YES; - } - - return NO; -} - - -/* Is it ice? */ - -int isice(float x, float y) -{ - if (shape(x, y) == '#') - { - return YES; - } - - return NO; -} - - -/* Is it a full box? */ - -int isfullbox(float x, float y) -{ - if (shape(x, y) == 'A' || - shape(x, y) == 'B' || - shape(x, y) == '!') - { - return YES; - } - - return NO; -} - -/* Break a brick: */ - -void trybreakbrick(float x, float y) -{ - if (isbrick(x, y)) - { - if (shape(x, y) == 'x' || shape(x, y) == 'y') - { - /* Get a distro from it: */ - - add_bouncy_distro(((int)(x + 1) / 32) * 32, - (int)(y / 32) * 32); - - if (counting_distros == NO) - { - counting_distros = YES; - distro_counter = 50; - } - - if (distro_counter <= 0) - level_change(¤t_level,x, y, 'a'); - - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); - score = score + SCORE_DISTRO; - distros++; - } - else - { - /* Get rid of it: */ - - level_change(¤t_level,x, y,'.'); - } - - - /* Replace it with broken bits: */ - - add_broken_brick(((int)(x + 1) / 32) * 32, - (int)(y / 32) * 32); - - - /* Get some score: */ - - play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); - score = score + SCORE_BRICK; - } -} - - -/* Bounce a brick: */ - -void bumpbrick(float x, float y) -{ - add_bouncy_brick(((int)(x + 1) / 32) * 32, - (int)(y / 32) * 32); - - play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); - -} - - -/* Empty a box: */ - -void tryemptybox(float x, float y, int col_side) -{ -if (!isfullbox(x, y)) - return; - -// according to the collision side, set the upgrade direction - -if(col_side == LEFT) - col_side = RIGHT; -else - col_side = LEFT; - -switch(shape(x,y)) - { - case 'A': /* Box with a distro! */ - add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32); - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); - score = score + SCORE_DISTRO; - distros++; - break; - case 'B': /* Add an upgrade! */ - if (tux.size == SMALL) /* Tux is small, add mints! */ - add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS); - else /* Tux is big, add coffee: */ - add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE); - play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER); - break; - case '!': /* Add a golden herring */ - add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING); - break; - default: - break; - } - -/* Empty the box: */ -level_change(¤t_level,x, y, 'a'); -} - - -/* Try to grab a distro: */ - -void trygrabdistro(float x, float y, int bounciness) -{ - if (shape(x, y) == '$') - { - level_change(¤t_level,x, y, '.'); - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); - - if (bounciness == BOUNCE) - { - add_bouncy_distro(((int)(x + 1) / 32) * 32, - (int)(y / 32) * 32); - } - - score = score + SCORE_DISTRO; - distros++; - } -} - -/* Try to bump a bad guy from below: */ - -void trybumpbadguy(float x, float y) -{ - int i; - - - /* Bad guys: */ - - for (i = 0; i < num_bad_guys; i++) - { - if (bad_guys[i].base.alive && - bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 && - bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16) - { - if (bad_guys[i].kind == BAD_BSOD || - bad_guys[i].kind == BAD_LAPTOP) - { - bad_guys[i].dying = FALLING; - bad_guys[i].base.ym = -8; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - } - } - } - - - /* Upgrades: */ - - for (i = 0; i < num_upgrades; i++) - { - if (upgrades[i].base.alive && upgrades[i].base.height == 32 && - upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 && - upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16) - { - upgrades[i].base.xm = -upgrades[i].base.xm; - upgrades[i].base.ym = -8; - play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER); - } - } -} - -/* (Status): */ -void drawstatus(void) -{ - int i; - - sprintf(str, "%d", score); - text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE); - text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE); - - if(st_gl_mode != ST_GL_TEST) - { - sprintf(str, "%d", hs_score); - text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE); - text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE); - } - else - { - text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE); - } - - if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5) - { - sprintf(str, "%d", timer_get_left(&time_left) / 1000 ); - text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE); - text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE); - } - - sprintf(str, "%d", distros); - text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE); - text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE); - - text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE); - - if(show_fps) - { - sprintf(str, "%2.1f", fps_fps); - text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE); - text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE); - } - - for(i=0; i < tux.lives; ++i) - { - texture_draw(&tux_life,565+(18*i),20,NO_UPDATE); - } -} - - -void drawendscreen(void) -{ - char str[80]; - - clearscreen(0, 0, 0); - - text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - sprintf(str, "SCORE: %d", score); - text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - sprintf(str, "DISTROS: %d", distros); - text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - flipscreen(); - SDL_Delay(2000); -} - -void drawresultscreen(void) -{ - char str[80]; - - clearscreen(0, 0, 0); - - text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - sprintf(str, "SCORE: %d", score); - text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - sprintf(str, "DISTROS: %d", distros); - text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - flipscreen(); - SDL_Delay(2000); -} - -void savegame(int slot) -{ - char savefile[1024]; - FILE* fi; - unsigned int ui; - - sprintf(savefile,"%s/slot%d.save",st_save_dir,slot); - - fi = fopen(savefile, "wb"); - - if (fi == NULL) - { - fprintf(stderr, "Warning: I could not open the slot file "); - - } - else - { - fputs(level_subset, fi); - fputs("\n", fi); - fwrite(&level,sizeof(int),1,fi); - fwrite(&score,sizeof(int),1,fi); - fwrite(&distros,sizeof(int),1,fi); - fwrite(&scroll_x,sizeof(float),1,fi); - fwrite(&tux,sizeof(player_type),1,fi); - timer_fwrite(&tux.invincible_timer,fi); - timer_fwrite(&tux.skidding_timer,fi); - timer_fwrite(&tux.safe_timer,fi); - timer_fwrite(&tux.frame_timer,fi); - timer_fwrite(&time_left,fi); - ui = st_get_ticks(); - fwrite(&ui,sizeof(int),1,fi); - } - fclose(fi); - -} - -void loadgame(int slot) -{ - char savefile[1024]; - char str[100]; - FILE* fi; - unsigned int ui; - - sprintf(savefile,"%s/slot%d.save",st_save_dir,slot); - - fi = fopen(savefile, "rb"); - - if (fi == NULL) - { - fprintf(stderr, "Warning: I could not open the slot file "); - - } - else - { - - - fgets(str, 100, fi); - strcpy(level_subset, str); - level_subset[strlen(level_subset)-1] = '\0'; - fread(&level,sizeof(int),1,fi); - - set_defaults(); - level_free(¤t_level); - if(level_load(¤t_level,level_subset,level) != 0) - exit(1); - arrays_free(); - arrays_init(); - activate_bad_guys(); - level_free_gfx(); - level_load_gfx(¤t_level); - level_free_song(); - level_load_song(¤t_level); - levelintro(); - update_time = st_get_ticks(); - - fread(&score,sizeof(int),1,fi); - fread(&distros,sizeof(int),1,fi); - fread(&scroll_x,sizeof(float),1,fi); - fread(&tux,sizeof(player_type),1,fi); - timer_fread(&tux.invincible_timer,fi); - timer_fread(&tux.skidding_timer,fi); - timer_fread(&tux.safe_timer,fi); - timer_fread(&tux.frame_timer,fi); - timer_fread(&time_left,fi); - fread(&ui,sizeof(int),1,fi); - tux.hphysic.start_time += st_get_ticks() - ui; - tux.vphysic.start_time += st_get_ticks() - ui; - fclose(fi); - } - -} - -void slotinfo(char **pinfo, int slot) -{ - FILE* fi; - char slotfile[1024]; - char tmp[200]; - char str[5]; - int slot_level; - sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot); - - fi = fopen(slotfile, "rb"); - - sprintf(tmp,"Slot %d - ",slot); - - if (fi == NULL) - { - strcat(tmp,"Free"); - } - else - { - fgets(str, 100, fi); - str[strlen(str)-1] = '\0'; - strcat(tmp, str); - strcat(tmp, " / Level:"); - fread(&slot_level,sizeof(int),1,fi); - sprintf(str,"%d",slot_level); - strcat(tmp,str); - fclose(fi); - } - - *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1)); - strcpy(*pinfo,tmp); - -} - diff --git a/src/gameloop.cpp b/src/gameloop.cpp new file mode 100644 index 000000000..5a39f066e --- /dev/null +++ b/src/gameloop.cpp @@ -0,0 +1,1807 @@ +/* + gameloop.c + + Super Tux - Game Loop! + + by Bill Kendrick & Tobias Glaesser + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 11, 2000 - March 15, 2004 + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef LINUX +#include +#include +#include +#endif + +#include "defines.h" +#include "globals.h" +#include "gameloop.h" +#include "screen.h" +#include "setup.h" +#include "high_scores.h" +#include "menu.h" +#include "badguy.h" +#include "world.h" +#include "special.h" +#include "player.h" +#include "level.h" +#include "scene.h" +#include "collision.h" + +/* extern variables */ + +st_level current_level; +int game_started = NO; + +/* Local variables: */ + +static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2]; +static texture_type img_cloud[2][4]; +static SDL_Event event; +static SDLKey key; +static char level_subset[100]; +static char str[60]; +static float fps_fps; +static int st_gl_mode; +static unsigned int last_update_time; +static unsigned int update_time; +static int pause_menu_frame; +static int debug_fps; + +/* Local function prototypes: */ + +void levelintro(void); +void loadshared(void); +void unloadshared(void); +void drawstatus(void); +void drawendscreen(void); +void drawresultscreen(void); + +#define JOYSTICK_DEAD_ZONE 4096 + +void levelintro(void) +{ + /* Level Intro: */ + + clearscreen(0, 0, 0); + + sprintf(str, "LEVEL %d", level); + text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + sprintf(str, "%s", current_level.name); + text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + sprintf(str, "TUX x %d", tux.lives); + text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + flipscreen(); + + SDL_Delay(1000); +} + +/* Reset Timers */ +void start_timers(void) +{ + timer_start(&time_left,current_level.time_left*1000); + st_pause_ticks_init(); + update_time = st_get_ticks(); +} + +void activate_bad_guys(void) +{ + int x,y; + + /* Activate bad guys: */ + + for (y = 0; y < 15; y++) + { + for (x = 0; x < current_level.width; x++) + { + if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9') + { + add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0'); + current_level.tiles[y][x] = '.'; + } + } + } + +} + +/* --- GAME EVENT! --- */ + +void game_event(void) +{ + while (SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_QUIT: /* Quit event - quit: */ + quit = 1; + break; + case SDL_KEYDOWN: /* A keypress! */ + key = event.key.keysym.sym; + + /* Check for menu-events, if the menu is shown */ + if(show_menu) + menu_event(&event.key.keysym); + + if(player_key_event(&tux,key,DOWN)) + break; + + switch(key) + { + case SDLK_ESCAPE: /* Escape: Open/Close the menu: */ + if(!game_pause) + { + if(st_gl_mode == ST_GL_TEST) + quit = 1; + else if(show_menu) + { + menu_set_current(&game_menu); + show_menu = 0; + st_pause_ticks_stop(); + } + else + { + menu_set_current(&game_menu); + show_menu = 1; + st_pause_ticks_start(); + } + } + break; + default: + break; + } + break; + case SDL_KEYUP: /* A keyrelease! */ + key = event.key.keysym.sym; + + if(player_key_event(&tux,key,UP)) + break; + + switch(key) + { + case SDLK_p: + if(!show_menu) + { + if(game_pause) + { + game_pause = 0; + st_pause_ticks_stop(); + } + else + { + game_pause = 1; + st_pause_ticks_start(); + } + } + break; + case SDLK_TAB: + if(debug_mode == YES) + { + tux.size = !tux.size; + if(tux.size == BIG) + { + tux.base.height = 64; + } + else + tux.base.height = 32; + } + break; + case SDLK_END: + if(debug_mode == YES) + distros += 50; + break; + case SDLK_SPACE: + if(debug_mode == YES) + next_level = 1; + break; + case SDLK_DELETE: + if(debug_mode == YES) + tux.got_coffee = 1; + break; + case SDLK_INSERT: + if(debug_mode == YES) + timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME); + break; + case SDLK_l: + if(debug_mode == YES) + --tux.lives; + break; + case SDLK_s: + if(debug_mode == YES) + score += 1000; + case SDLK_f: + if(debug_fps == YES) + debug_fps = NO; + else + debug_fps = YES; + break; + default: + break; + } + break; +#ifdef JOY_YES + + case SDL_JOYAXISMOTION: + switch(event.jaxis.axis) + { + case JOY_X: + if (event.jaxis.value < -JOYSTICK_DEAD_ZONE) + tux.input.left = DOWN; + else if (event.jaxis.value > JOYSTICK_DEAD_ZONE) + tux.input.left = UP; + + if (event.jaxis.value > JOYSTICK_DEAD_ZONE) + tux.input.right = DOWN; + else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE) + tux.input.right = UP; + break; + case JOY_Y: + if (event.jaxis.value > JOYSTICK_DEAD_ZONE) + tux.input.down = DOWN; + else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE) + tux.input.down = UP; + + /* Handle joystick for the menu */ + if(show_menu) + { + if(tux.input.down == DOWN) + menuaction = MN_DOWN; + else + menuaction = MN_UP; + } + break; + default: + break; + } + break; + case SDL_JOYBUTTONDOWN: + if (event.jbutton.button == JOY_A) + tux.input.up = DOWN; + else if (event.jbutton.button == JOY_B) + tux.input.fire = DOWN; + break; + case SDL_JOYBUTTONUP: + if (event.jbutton.button == JOY_A) + tux.input.up = UP; + else if (event.jbutton.button == JOY_B) + tux.input.fire = UP; + + if(show_menu) + menuaction = MN_HIT; + break; + +#endif + default: + break; + + } /* switch */ + + } /* while */ + +} + +/* --- GAME ACTION! --- */ + +int game_action(void) +{ + int i; + + /* (tux_dying || next_level) */ + if (tux.dying || next_level) + { + /* Tux either died, or reached the end of a level! */ + + halt_music(); + + + if (next_level) + { + /* End of a level! */ + level++; + next_level = 0; + if(st_gl_mode != ST_GL_TEST) + { + drawresultscreen(); + } + else + { + level_free_gfx(); + level_free(¤t_level); + level_free_song(); + unloadshared(); + arrays_free(); + return(0); + } + player_level_begin(&tux); + } + else + { + player_dying(&tux); + + /* No more lives!? */ + + if (tux.lives < 0) + { + if(st_gl_mode != ST_GL_TEST) + drawendscreen(); + + if(st_gl_mode != ST_GL_TEST) + { + if (score > hs_score) + save_hs(score); + } + level_free_gfx(); + level_free(¤t_level); + level_free_song(); + unloadshared(); + arrays_free(); + return(0); + } /* if (lives < 0) */ + } + + /* Either way, (re-)load the (next) level... */ + + player_level_begin(&tux); + set_defaults(); + level_free(¤t_level); + if(level_load(¤t_level,level_subset,level) != 0) + return 0; + arrays_free(); + arrays_init(); + activate_bad_guys(); + level_free_gfx(); + level_load_gfx(¤t_level); + level_free_song(); + level_load_song(¤t_level); + if(st_gl_mode != ST_GL_TEST) + levelintro(); + start_timers(); + /* Play music: */ + play_current_music(); + } + + player_action(&tux); + + /* Handle bouncy distros: */ + + for (i = 0; i < num_bouncy_distros; i++) + { + bouncy_distro_action(&bouncy_distros[i]); + } + + + /* Handle broken bricks: */ + + for (i = 0; i < num_broken_bricks; i++) + { + broken_brick_action(&broken_bricks[i]); + } + + + /* Handle distro counting: */ + + if (counting_distros == YES) + { + distro_counter--; + + if (distro_counter <= 0) + counting_distros = -1; + } + + + /* Handle bouncy bricks: */ + + for (i = 0; i < num_bouncy_bricks; i++) + { + bouncy_brick_action(&bouncy_bricks[i]); + } + + + /* Handle floating scores: */ + + for (i = 0; i < num_floating_scores; i++) + { + floating_score_action(&floating_scores[i]); + } + + + /* Handle bullets: */ + + for (i = 0; i < num_bullets; ++i) + { + bullet_action(&bullets[i]); + } + + /* Handle upgrades: */ + + for (i = 0; i < num_upgrades; i++) + { + upgrade_action(&upgrades[i]); + } + + + /* Handle bad guys: */ + + for (i = 0; i < num_bad_guys; i++) + { + badguy_action(&bad_guys[i]); + } + + /* Handle all possible collisions. */ + collision_handler(); + + return -1; +} + +/* --- GAME DRAW! --- */ + +void game_draw(void) +{ + int x, y, i, s; + + /* Draw screen: */ + + if (tux.dying && (frame % 4) == 0) + clearscreen(255, 255, 255); + else if(timer_check(&super_bkgd_timer)) + texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE); + else + { + /* Draw the real background */ + if(current_level.bkgd_image[0] != '\0') + { + s = (int)scroll_x / 30; + texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE); + texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE); + } + else + { + clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); + } + } + + /* Draw background: */ + + for (y = 0; y < 15; ++y) + { + for (x = 0; x < 21; ++x) + { + drawshape(x * 32 - ((int)scroll_x % 32), y * 32, + current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]); + } + } + + + /* (Bouncy bricks): */ + + for (i = 0; i < num_bouncy_bricks; ++i) + { + bouncy_brick_draw(&bouncy_bricks[i]); + } + + + /* (Bad guys): */ + + for (i = 0; i < num_bad_guys; ++i) + { + badguy_draw(&bad_guys[i]); + } + + /* (Tux): */ + + player_draw(&tux); + + /* (Bullets): */ + + for (i = 0; i < num_bullets; ++i) + { + bullet_draw(&bullets[i]); + } + + /* (Floating scores): */ + + for (i = 0; i < num_floating_scores; ++i) + { + floating_score_draw(&floating_scores[i]); + } + + + /* (Upgrades): */ + + for (i = 0; i < num_upgrades; ++i) + { + upgrade_draw(&upgrades[i]); + } + + + /* (Bouncy distros): */ + + for (i = 0; i < num_bouncy_distros; ++i) + { + bouncy_distro_draw(&bouncy_distros[i]); + } + + + /* (Broken bricks): */ + + for (i = 0; i < num_broken_bricks; ++i) + { + broken_brick_draw(&broken_bricks[i]); + } + + drawstatus(); + + + if(game_pause) + { + x = screen->h / 20; + for(i = 0; i < x; ++i) + { + fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1); + } + fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128); + text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + } + + if(show_menu) + menu_process_current(); + + /* (Update it all!) */ + + updatescreen(); + + +} + +/* --- GAME LOOP! --- */ + +int gameloop(char * subset, int levelnb, int mode) +{ + int fps_cnt, jump, done; + timer_type fps_timer, frame_timer; + timer_init(&fps_timer, YES); + timer_init(&frame_timer, YES); + + game_started = YES; + + st_gl_mode = mode; + level = levelnb; + strcpy(level_subset,subset); + + /* Init the game: */ + arrays_init(); + set_defaults(); + + if(level_load(¤t_level,level_subset,level) != 0) + exit(1); + level_load_gfx(¤t_level); + activate_bad_guys(); + level_load_song(¤t_level); + + player_init(&tux); + + if(st_gl_mode != ST_GL_TEST) + load_hs(); + + loadshared(); + + if(st_gl_mode == ST_GL_PLAY) + levelintro(); + + + timer_init(&time_left,YES); + start_timers(); + + if(st_gl_mode == ST_GL_LOAD_GAME) + loadgame(levelnb); + + + /* --- MAIN GAME LOOP!!! --- */ + + jump = NO; + done = 0; + quit = 0; + frame = 0; + game_pause = 0; + timer_init(&fps_timer,YES); + timer_init(&frame_timer,YES); + fps_cnt = 0; + + /* Clear screen: */ + + clearscreen(0, 0, 0); + updatescreen(); + + /* Play music: */ + play_current_music(); + + + while (SDL_PollEvent(&event)) + {} + + game_draw(); + do + { + jump = NO; + + /* Calculate the movement-factor */ + frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE); + if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */ + frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85; + + if(!timer_check(&frame_timer)) + { + timer_start(&frame_timer,25); + ++frame; + } + + /* Handle events: */ + + tux.input.old_fire = tux.input.fire; + + game_event(); + + if(show_menu) + { + if(current_menu == &game_menu) + { + switch (menu_check(&game_menu)) + { + case 2: + st_pause_ticks_stop(); + break; + case 3: + update_load_save_game_menu(&save_game_menu, NO); + break; + case 4: + update_load_save_game_menu(&load_game_menu, YES); + break; + case 7: + st_pause_ticks_stop(); + done = 1; + break; + } + } + else if(current_menu == &options_menu) + { + process_options_menu(); + } + else if(current_menu == &save_game_menu ) + { + process_save_load_game_menu(YES); + } + else if(current_menu == &load_game_menu ) + { + process_save_load_game_menu(NO); + } + } + + + /* Handle actions: */ + + if(!game_pause && !show_menu) + { + /*float z = frame_ratio; + frame_ratio = 1; + while(z >= 1) + {*/ + if (game_action() == 0) + { + /* == 0: no more lives */ + /* == -1: continues */ + return 0; + } + /* --z; + }*/ + } + else + { + ++pause_menu_frame; + SDL_Delay(50); + } + + if(debug_mode && debug_fps == YES) + SDL_Delay(60); + + /*Draw the current scene to the screen */ + /*If the machine running the game is too slow + skip the drawing of the frame (so the calculations are more precise and + the FPS aren't affected).*/ + /*if( ! fps_fps < 50.0 ) + game_draw(); + else + jump = YES;*/ /*FIXME: Implement this tweak right.*/ + game_draw(); + + /* Time stops in pause mode */ + if(game_pause || show_menu ) + { + continue; + } + + /* Set the time of the last update and the time of the current update */ + last_update_time = update_time; + update_time = st_get_ticks(); + + + /* Pause till next frame, if the machine running the game is too fast: */ + /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But + the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */ + if(last_update_time >= update_time - 12 && jump != YES ) + SDL_Delay(10); + /*if((update_time - last_update_time) < 10) + SDL_Delay((11 - (update_time - last_update_time))/2);*/ + + + + /* Handle time: */ + + if (timer_check(&time_left)) + { + /* are we low on time ? */ + if ((timer_get_left(&time_left) < TIME_WARNING) + && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */ + { + set_current_music(HURRYUP_MUSIC); + play_current_music(); + } + + } + else + player_kill(&tux,KILL); + + + /* Calculate frames per second */ + if(show_fps) + { + ++fps_cnt; + fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt; + + if(!timer_check(&fps_timer)) + { + timer_start(&fps_timer,1000); + fps_cnt = 0; + } + } + + } + while (!done && !quit); + + halt_music(); + + level_free_gfx(); + level_free(¤t_level); + level_free_song(); + unloadshared(); + arrays_free(); + + game_started = NO; + + return(quit); +} + + +/* Load graphics/sounds shared between all levels: */ + +void loadshared(void) +{ + int i; + char * herring_song_path; /* for loading herring song*/ + + /* Tuxes: */ + + texture_load(&tux_right[0],DATA_PREFIX "/images/shared/tux-right-0.png", USE_ALPHA); + texture_load(&tux_right[1],DATA_PREFIX "/images/shared/tux-right-1.png", USE_ALPHA); + texture_load(&tux_right[2],DATA_PREFIX "/images/shared/tux-right-2.png", USE_ALPHA); + + texture_load(&tux_left[0],DATA_PREFIX "/images/shared/tux-left-0.png", USE_ALPHA); + texture_load(&tux_left[1],DATA_PREFIX "/images/shared/tux-left-1.png", USE_ALPHA); + texture_load(&tux_left[2],DATA_PREFIX "/images/shared/tux-left-2.png", USE_ALPHA); + + texture_load(&firetux_right[0],DATA_PREFIX "/images/shared/firetux-right-0.png", USE_ALPHA); + texture_load(&firetux_right[1],DATA_PREFIX "/images/shared/firetux-right-1.png", USE_ALPHA); + texture_load(&firetux_right[2],DATA_PREFIX "/images/shared/firetux-right-2.png", USE_ALPHA); + + texture_load(&firetux_left[0],DATA_PREFIX "/images/shared/firetux-left-0.png", USE_ALPHA); + texture_load(&firetux_left[1],DATA_PREFIX "/images/shared/firetux-left-1.png", USE_ALPHA); + texture_load(&firetux_left[2],DATA_PREFIX "/images/shared/firetux-left-2.png", USE_ALPHA); + + + texture_load(&cape_right[0] ,DATA_PREFIX "/images/shared/cape-right-0.png", + USE_ALPHA); + + texture_load(&cape_right[1] ,DATA_PREFIX "/images/shared/cape-right-1.png", + USE_ALPHA); + + texture_load(&cape_left[0] ,DATA_PREFIX "/images/shared/cape-left-0.png", + USE_ALPHA); + + texture_load(&cape_left[1] ,DATA_PREFIX "/images/shared/cape-left-1.png", + USE_ALPHA); + + texture_load(&bigtux_right[0] ,DATA_PREFIX "/images/shared/bigtux-right-0.png", + USE_ALPHA); + + texture_load(&bigtux_right[1] ,DATA_PREFIX "/images/shared/bigtux-right-1.png", + USE_ALPHA); + + texture_load(&bigtux_right[2] ,DATA_PREFIX "/images/shared/bigtux-right-2.png", + USE_ALPHA); + + texture_load(&bigtux_right_jump ,DATA_PREFIX "/images/shared/bigtux-right-jump.png", USE_ALPHA); + + texture_load(&bigtux_left[0] ,DATA_PREFIX "/images/shared/bigtux-left-0.png", + USE_ALPHA); + + texture_load(&bigtux_left[1] ,DATA_PREFIX "/images/shared/bigtux-left-1.png", + USE_ALPHA); + + texture_load(&bigtux_left[2] ,DATA_PREFIX "/images/shared/bigtux-left-2.png", + USE_ALPHA); + + texture_load(&bigtux_left_jump ,DATA_PREFIX "/images/shared/bigtux-left-jump.png", USE_ALPHA); + + texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png", + USE_ALPHA); + + texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png", + USE_ALPHA); + + texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png", + USE_ALPHA); + + texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png", + USE_ALPHA); + + texture_load(&bigfiretux_right[0] ,DATA_PREFIX "/images/shared/bigfiretux-right-0.png", + USE_ALPHA); + + texture_load(&bigfiretux_right[1] ,DATA_PREFIX "/images/shared/bigfiretux-right-1.png", + USE_ALPHA); + + texture_load(&bigfiretux_right[2] ,DATA_PREFIX "/images/shared/bigfiretux-right-2.png", + USE_ALPHA); + + texture_load(&bigfiretux_right_jump ,DATA_PREFIX "/images/shared/bigfiretux-right-jump.png", USE_ALPHA); + + texture_load(&bigfiretux_left[0] ,DATA_PREFIX "/images/shared/bigfiretux-left-0.png", + USE_ALPHA); + + texture_load(&bigfiretux_left[1] ,DATA_PREFIX "/images/shared/bigfiretux-left-1.png", + USE_ALPHA); + + texture_load(&bigfiretux_left[2] ,DATA_PREFIX "/images/shared/bigfiretux-left-2.png", + USE_ALPHA); + + texture_load(&bigfiretux_left_jump ,DATA_PREFIX "/images/shared/bigfiretux-left-jump.png", USE_ALPHA); + + texture_load(&bigcape_right[0] ,DATA_PREFIX "/images/shared/bigcape-right-0.png", + USE_ALPHA); + + texture_load(&bigcape_right[1] ,DATA_PREFIX "/images/shared/bigcape-right-1.png", + USE_ALPHA); + + texture_load(&bigcape_left[0] ,DATA_PREFIX "/images/shared/bigcape-left-0.png", + USE_ALPHA); + + texture_load(&bigcape_left[1] ,DATA_PREFIX "/images/shared/bigcape-left-1.png", + USE_ALPHA); + + + texture_load(&ducktux_right ,DATA_PREFIX + "/images/shared/ducktux-right.png", + USE_ALPHA); + + texture_load(&ducktux_left ,DATA_PREFIX + "/images/shared/ducktux-left.png", + USE_ALPHA); + + texture_load(&skidtux_right ,DATA_PREFIX + "/images/shared/skidtux-right.png", + USE_ALPHA); + + texture_load(&skidtux_left ,DATA_PREFIX + "/images/shared/skidtux-left.png", + USE_ALPHA); + + texture_load(&duckfiretux_right ,DATA_PREFIX + "/images/shared/duckfiretux-right.png", + USE_ALPHA); + + texture_load(&duckfiretux_left ,DATA_PREFIX + "/images/shared/duckfiretux-left.png", + USE_ALPHA); + + texture_load(&skidfiretux_right ,DATA_PREFIX + "/images/shared/skidfiretux-right.png", + USE_ALPHA); + + texture_load(&skidfiretux_left ,DATA_PREFIX + "/images/shared/skidfiretux-left.png", + USE_ALPHA); + + + /* Boxes: */ + + texture_load(&img_box_full ,DATA_PREFIX "/images/shared/box-full.png", + IGNORE_ALPHA); + texture_load(&img_box_empty ,DATA_PREFIX "/images/shared/box-empty.png", + IGNORE_ALPHA); + + + /* Water: */ + + + texture_load(&img_water ,DATA_PREFIX "/images/shared/water.png", IGNORE_ALPHA); + + texture_load(&img_waves[0] ,DATA_PREFIX "/images/shared/waves-0.png", + USE_ALPHA); + + texture_load(&img_waves[1] ,DATA_PREFIX "/images/shared/waves-1.png", + USE_ALPHA); + + texture_load(&img_waves[2] ,DATA_PREFIX "/images/shared/waves-2.png", + USE_ALPHA); + + + /* Pole: */ + + texture_load(&img_pole ,DATA_PREFIX "/images/shared/pole.png", USE_ALPHA); + texture_load(&img_poletop ,DATA_PREFIX "/images/shared/poletop.png", + USE_ALPHA); + + + /* Flag: */ + + texture_load(&img_flag[0] ,DATA_PREFIX "/images/shared/flag-0.png", + USE_ALPHA); + texture_load(&img_flag[1] ,DATA_PREFIX "/images/shared/flag-1.png", + USE_ALPHA); + + + /* Cloud: */ + + texture_load(&img_cloud[0][0] ,DATA_PREFIX "/images/shared/cloud-00.png", + USE_ALPHA); + + texture_load(&img_cloud[0][1] ,DATA_PREFIX "/images/shared/cloud-01.png", + USE_ALPHA); + + texture_load(&img_cloud[0][2] ,DATA_PREFIX "/images/shared/cloud-02.png", + USE_ALPHA); + + texture_load(&img_cloud[0][3] ,DATA_PREFIX "/images/shared/cloud-03.png", + USE_ALPHA); + + + texture_load(&img_cloud[1][0] ,DATA_PREFIX "/images/shared/cloud-10.png", + USE_ALPHA); + + texture_load(&img_cloud[1][1] ,DATA_PREFIX "/images/shared/cloud-11.png", + USE_ALPHA); + + texture_load(&img_cloud[1][2] ,DATA_PREFIX "/images/shared/cloud-12.png", + USE_ALPHA); + + texture_load(&img_cloud[1][3] ,DATA_PREFIX "/images/shared/cloud-13.png", + USE_ALPHA); + + + /* Bad guys: */ + + /* (BSOD) */ + + texture_load(&img_bsod_left[0] ,DATA_PREFIX + "/images/shared/bsod-left-0.png", + USE_ALPHA); + + texture_load(&img_bsod_left[1] ,DATA_PREFIX + "/images/shared/bsod-left-1.png", + USE_ALPHA); + + texture_load(&img_bsod_left[2] ,DATA_PREFIX + "/images/shared/bsod-left-2.png", + USE_ALPHA); + + texture_load(&img_bsod_left[3] ,DATA_PREFIX + "/images/shared/bsod-left-3.png", + USE_ALPHA); + + texture_load(&img_bsod_right[0] ,DATA_PREFIX + "/images/shared/bsod-right-0.png", + USE_ALPHA); + + texture_load(&img_bsod_right[1] ,DATA_PREFIX + "/images/shared/bsod-right-1.png", + USE_ALPHA); + + texture_load(&img_bsod_right[2] ,DATA_PREFIX + "/images/shared/bsod-right-2.png", + USE_ALPHA); + + texture_load(&img_bsod_right[3] ,DATA_PREFIX + "/images/shared/bsod-right-3.png", + USE_ALPHA); + + texture_load(&img_bsod_squished_left ,DATA_PREFIX + "/images/shared/bsod-squished-left.png", + USE_ALPHA); + + texture_load(&img_bsod_squished_right ,DATA_PREFIX + "/images/shared/bsod-squished-right.png", + USE_ALPHA); + + texture_load(&img_bsod_falling_left ,DATA_PREFIX + "/images/shared/bsod-falling-left.png", + USE_ALPHA); + + texture_load(&img_bsod_falling_right ,DATA_PREFIX + "/images/shared/bsod-falling-right.png", + USE_ALPHA); + + + /* (Laptop) */ + + texture_load(&img_laptop_left[0] ,DATA_PREFIX + "/images/shared/laptop-left-0.png", + USE_ALPHA); + + texture_load(&img_laptop_left[1] ,DATA_PREFIX + "/images/shared/laptop-left-1.png", + USE_ALPHA); + + texture_load(&img_laptop_left[2] ,DATA_PREFIX + "/images/shared/laptop-left-2.png", + USE_ALPHA); + + texture_load(&img_laptop_right[0] ,DATA_PREFIX + "/images/shared/laptop-right-0.png", + USE_ALPHA); + + texture_load(&img_laptop_right[1] ,DATA_PREFIX + "/images/shared/laptop-right-1.png", + USE_ALPHA); + + texture_load(&img_laptop_right[2] ,DATA_PREFIX + "/images/shared/laptop-right-2.png", + USE_ALPHA); + + texture_load(&img_laptop_flat_left ,DATA_PREFIX + "/images/shared/laptop-flat-left.png", + USE_ALPHA); + + texture_load(&img_laptop_flat_right ,DATA_PREFIX + "/images/shared/laptop-flat-right.png", + USE_ALPHA); + + texture_load(&img_laptop_falling_left ,DATA_PREFIX + "/images/shared/laptop-falling-left.png", + USE_ALPHA); + + texture_load(&img_laptop_falling_right ,DATA_PREFIX + "/images/shared/laptop-falling-right.png", + USE_ALPHA); + + + /* (Money) */ + + texture_load(&img_money_left[0] ,DATA_PREFIX + "/images/shared/bag-left-0.png", + USE_ALPHA); + + texture_load(&img_money_left[1] ,DATA_PREFIX + "/images/shared/bag-left-1.png", + USE_ALPHA); + + texture_load(&img_money_right[0] ,DATA_PREFIX + "/images/shared/bag-right-0.png", + USE_ALPHA); + + texture_load(&img_money_right[1] ,DATA_PREFIX + "/images/shared/bag-right-1.png", + USE_ALPHA); + + + + /* Upgrades: */ + + texture_load(&img_mints ,DATA_PREFIX "/images/shared/mints.png", USE_ALPHA); + texture_load(&img_coffee ,DATA_PREFIX "/images/shared/coffee.png", USE_ALPHA); + + + /* Weapons: */ + + texture_load(&img_bullet ,DATA_PREFIX "/images/shared/bullet.png", USE_ALPHA); + + texture_load(&img_red_glow ,DATA_PREFIX "/images/shared/red-glow.png", + USE_ALPHA); + + + + /* Distros: */ + + texture_load(&img_distro[0] ,DATA_PREFIX "/images/shared/distro-0.png", + USE_ALPHA); + + texture_load(&img_distro[1] ,DATA_PREFIX "/images/shared/distro-1.png", + USE_ALPHA); + + texture_load(&img_distro[2] ,DATA_PREFIX "/images/shared/distro-2.png", + USE_ALPHA); + + texture_load(&img_distro[3] ,DATA_PREFIX "/images/shared/distro-3.png", + USE_ALPHA); + + + /* Tux life: */ + + texture_load(&tux_life ,DATA_PREFIX "/images/shared/tux-life.png", + USE_ALPHA); + + /* Herring: */ + + texture_load(&img_golden_herring, DATA_PREFIX "/images/shared/golden-herring.png", + USE_ALPHA); + + + /* Super background: */ + + texture_load(&img_super_bkgd ,DATA_PREFIX "/images/shared/super-bkgd.png", + IGNORE_ALPHA); + + + /* Sound effects: */ + + /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound" + // initialize sounds[i] with the correct pointer's value: + // NULL or something else. And it will be dangerous to + // play with not-initialized pointers. + // This is also true with if (use_music) + Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :) + */ + for (i = 0; i < NUM_SOUNDS; i++) + sounds[i] = load_sound(soundfilenames[i]); + + /* Herring song */ + herring_song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + + strlen("SALCON.MOD") + 8)); + + sprintf(herring_song_path, "%s/music/%s", DATA_PREFIX, "SALCON.MOD"); + + herring_song = load_song(herring_song_path); + + free(herring_song_path); + +} + + +/* Free shared data: */ + +void unloadshared(void) +{ + int i; + + for (i = 0; i < 3; i++) + { + texture_free(&tux_right[i]); + texture_free(&tux_left[i]); + texture_free(&bigtux_right[i]); + texture_free(&bigtux_left[i]); + } + + texture_free(&bigtux_right_jump); + texture_free(&bigtux_left_jump); + + for (i = 0; i < 2; i++) + { + texture_free(&cape_right[i]); + texture_free(&cape_left[i]); + texture_free(&bigcape_right[i]); + texture_free(&bigcape_left[i]); + } + + texture_free(&ducktux_left); + texture_free(&ducktux_right); + + texture_free(&skidtux_left); + texture_free(&skidtux_right); + + for (i = 0; i < 4; i++) + { + texture_free(&img_bsod_left[i]); + texture_free(&img_bsod_right[i]); + } + + texture_free(&img_bsod_squished_left); + texture_free(&img_bsod_squished_right); + + texture_free(&img_bsod_falling_left); + texture_free(&img_bsod_falling_right); + + for (i = 0; i < 3; i++) + { + texture_free(&img_laptop_left[i]); + texture_free(&img_laptop_right[i]); + } + + texture_free(&img_laptop_flat_left); + texture_free(&img_laptop_flat_right); + + texture_free(&img_laptop_falling_left); + texture_free(&img_laptop_falling_right); + + for (i = 0; i < 2; i++) + { + texture_free(&img_money_left[i]); + texture_free(&img_money_right[i]); + } + + texture_free(&img_box_full); + texture_free(&img_box_empty); + + texture_free(&img_water); + for (i = 0; i < 3; i++) + texture_free(&img_waves[i]); + + texture_free(&img_pole); + texture_free(&img_poletop); + + for (i = 0; i < 2; i++) + texture_free(&img_flag[i]); + + texture_free(&img_mints); + texture_free(&img_coffee); + + for (i = 0; i < 4; i++) + { + texture_free(&img_distro[i]); + texture_free(&img_cloud[0][i]); + texture_free(&img_cloud[1][i]); + } + + texture_free(&img_golden_herring); + + for (i = 0; i < NUM_SOUNDS; i++) + free_chunk(sounds[i]); + + /* free the herring song */ + free_music( herring_song ); +} + + +/* Draw a tile on the screen: */ + +void drawshape(float x, float y, unsigned char c) +{ + int z; + + if (c == 'X' || c == 'x') + texture_draw(&img_brick[0], x, y, NO_UPDATE); + else if (c == 'Y' || c == 'y') + texture_draw(&img_brick[1], x, y, NO_UPDATE); + else if (c == 'A' || c =='B' || c == '!') + texture_draw(&img_box_full, x, y, NO_UPDATE); + else if (c == 'a') + texture_draw(&img_box_empty, x, y, NO_UPDATE); + else if (c >= 'C' && c <= 'F') + texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE); + else if (c >= 'c' && c <= 'f') + texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE); + else if (c >= 'G' && c <= 'J') + texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE); + else if (c >= 'g' && c <= 'j') + texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE); + else if (c == '#') + texture_draw(&img_solid[0], x, y, NO_UPDATE); + else if (c == '[') + texture_draw(&img_solid[1], x, y, NO_UPDATE); + else if (c == '=') + texture_draw(&img_solid[2], x, y, NO_UPDATE); + else if (c == ']') + texture_draw(&img_solid[3], x, y, NO_UPDATE); + else if (c == '$') + { + + z = (frame / 2) % 6; + + if (z < 4) + texture_draw(&img_distro[z], x, y, NO_UPDATE); + else if (z == 4) + texture_draw(&img_distro[2], x, y, NO_UPDATE); + else if (z == 5) + texture_draw(&img_distro[1], x, y, NO_UPDATE); + } + else if (c == '^') + { + z = (frame / 3) % 3; + + texture_draw(&img_waves[z], x, y, NO_UPDATE); + } + else if (c == '*') + texture_draw(&img_poletop, x, y, NO_UPDATE); + else if (c == '|') + { + texture_draw(&img_pole, x, y, NO_UPDATE); + + } + else if (c == '\\') + { + z = (frame / 3) % 2; + + texture_draw(&img_flag[z], x + 16, y, NO_UPDATE); + } + else if (c == '&') + texture_draw(&img_water, x, y, NO_UPDATE); +} + + +/* What shape is at some position? */ + +unsigned char shape(float x, float y) +{ + + int xx, yy; + unsigned char c; + + yy = ((int)y / 32); + xx = ((int)x / 32); + + if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width) + { + c = current_level.tiles[yy][xx]; + } + else + c = '.'; + + return(c); +} + +/* Is is ground? */ + + +int issolid(float x, float y) +{ + if (isbrick(x, y) || + isice(x, y) || + (shape(x, y) == '[') || + (shape(x, y) == '=') || + (shape(x, y) == ']') || + (shape(x, y) == 'A') || + (shape(x, y) == 'B') || + (shape(x, y) == '!') || + (shape(x, y) == 'a')) + { + return YES; + } + + return NO; +} + + +/* Is it a brick? */ + +int isbrick(float x, float y) +{ + if (shape(x, y) == 'X' || + shape(x, y) == 'x' || + shape(x, y) == 'Y' || + shape(x, y) == 'y') + { + return YES; + } + + return NO; +} + + +/* Is it ice? */ + +int isice(float x, float y) +{ + if (shape(x, y) == '#') + { + return YES; + } + + return NO; +} + + +/* Is it a full box? */ + +int isfullbox(float x, float y) +{ + if (shape(x, y) == 'A' || + shape(x, y) == 'B' || + shape(x, y) == '!') + { + return YES; + } + + return NO; +} + +/* Break a brick: */ + +void trybreakbrick(float x, float y) +{ + if (isbrick(x, y)) + { + if (shape(x, y) == 'x' || shape(x, y) == 'y') + { + /* Get a distro from it: */ + + add_bouncy_distro(((int)(x + 1) / 32) * 32, + (int)(y / 32) * 32); + + if (counting_distros == NO) + { + counting_distros = YES; + distro_counter = 50; + } + + if (distro_counter <= 0) + level_change(¤t_level,x, y, 'a'); + + play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + score = score + SCORE_DISTRO; + distros++; + } + else + { + /* Get rid of it: */ + + level_change(¤t_level,x, y,'.'); + } + + + /* Replace it with broken bits: */ + + add_broken_brick(((int)(x + 1) / 32) * 32, + (int)(y / 32) * 32); + + + /* Get some score: */ + + play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); + score = score + SCORE_BRICK; + } +} + + +/* Bounce a brick: */ + +void bumpbrick(float x, float y) +{ + add_bouncy_brick(((int)(x + 1) / 32) * 32, + (int)(y / 32) * 32); + + play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); + +} + + +/* Empty a box: */ + +void tryemptybox(float x, float y, int col_side) +{ +if (!isfullbox(x, y)) + return; + +// according to the collision side, set the upgrade direction + +if(col_side == LEFT) + col_side = RIGHT; +else + col_side = LEFT; + +switch(shape(x,y)) + { + case 'A': /* Box with a distro! */ + add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32); + play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + score = score + SCORE_DISTRO; + distros++; + break; + case 'B': /* Add an upgrade! */ + if (tux.size == SMALL) /* Tux is small, add mints! */ + add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS); + else /* Tux is big, add coffee: */ + add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE); + play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER); + break; + case '!': /* Add a golden herring */ + add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING); + break; + default: + break; + } + +/* Empty the box: */ +level_change(¤t_level,x, y, 'a'); +} + + +/* Try to grab a distro: */ + +void trygrabdistro(float x, float y, int bounciness) +{ + if (shape(x, y) == '$') + { + level_change(¤t_level,x, y, '.'); + play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + + if (bounciness == BOUNCE) + { + add_bouncy_distro(((int)(x + 1) / 32) * 32, + (int)(y / 32) * 32); + } + + score = score + SCORE_DISTRO; + distros++; + } +} + +/* Try to bump a bad guy from below: */ + +void trybumpbadguy(float x, float y) +{ + int i; + + + /* Bad guys: */ + + for (i = 0; i < num_bad_guys; i++) + { + if (bad_guys[i].base.alive && + bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 && + bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16) + { + if (bad_guys[i].kind == BAD_BSOD || + bad_guys[i].kind == BAD_LAPTOP) + { + bad_guys[i].dying = FALLING; + bad_guys[i].base.ym = -8; + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + } + } + } + + + /* Upgrades: */ + + for (i = 0; i < num_upgrades; i++) + { + if (upgrades[i].base.alive && upgrades[i].base.height == 32 && + upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 && + upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16) + { + upgrades[i].base.xm = -upgrades[i].base.xm; + upgrades[i].base.ym = -8; + play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER); + } + } +} + +/* (Status): */ +void drawstatus(void) +{ + int i; + + sprintf(str, "%d", score); + text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE); + text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE); + + if(st_gl_mode != ST_GL_TEST) + { + sprintf(str, "%d", hs_score); + text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE); + text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE); + } + else + { + text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE); + } + + if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5) + { + sprintf(str, "%d", timer_get_left(&time_left) / 1000 ); + text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE); + text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE); + } + + sprintf(str, "%d", distros); + text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE); + text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE); + + text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE); + + if(show_fps) + { + sprintf(str, "%2.1f", fps_fps); + text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE); + text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE); + } + + for(i=0; i < tux.lives; ++i) + { + texture_draw(&tux_life,565+(18*i),20,NO_UPDATE); + } +} + + +void drawendscreen(void) +{ + char str[80]; + + clearscreen(0, 0, 0); + + text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + sprintf(str, "SCORE: %d", score); + text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + sprintf(str, "DISTROS: %d", distros); + text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + flipscreen(); + SDL_Delay(2000); +} + +void drawresultscreen(void) +{ + char str[80]; + + clearscreen(0, 0, 0); + + text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + sprintf(str, "SCORE: %d", score); + text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + sprintf(str, "DISTROS: %d", distros); + text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + flipscreen(); + SDL_Delay(2000); +} + +void savegame(int slot) +{ + char savefile[1024]; + FILE* fi; + unsigned int ui; + + sprintf(savefile,"%s/slot%d.save",st_save_dir,slot); + + fi = fopen(savefile, "wb"); + + if (fi == NULL) + { + fprintf(stderr, "Warning: I could not open the slot file "); + + } + else + { + fputs(level_subset, fi); + fputs("\n", fi); + fwrite(&level,sizeof(int),1,fi); + fwrite(&score,sizeof(int),1,fi); + fwrite(&distros,sizeof(int),1,fi); + fwrite(&scroll_x,sizeof(float),1,fi); + fwrite(&tux,sizeof(player_type),1,fi); + timer_fwrite(&tux.invincible_timer,fi); + timer_fwrite(&tux.skidding_timer,fi); + timer_fwrite(&tux.safe_timer,fi); + timer_fwrite(&tux.frame_timer,fi); + timer_fwrite(&time_left,fi); + ui = st_get_ticks(); + fwrite(&ui,sizeof(int),1,fi); + } + fclose(fi); + +} + +void loadgame(int slot) +{ + char savefile[1024]; + char str[100]; + FILE* fi; + unsigned int ui; + + sprintf(savefile,"%s/slot%d.save",st_save_dir,slot); + + fi = fopen(savefile, "rb"); + + if (fi == NULL) + { + fprintf(stderr, "Warning: I could not open the slot file "); + + } + else + { + + + fgets(str, 100, fi); + strcpy(level_subset, str); + level_subset[strlen(level_subset)-1] = '\0'; + fread(&level,sizeof(int),1,fi); + + set_defaults(); + level_free(¤t_level); + if(level_load(¤t_level,level_subset,level) != 0) + exit(1); + arrays_free(); + arrays_init(); + activate_bad_guys(); + level_free_gfx(); + level_load_gfx(¤t_level); + level_free_song(); + level_load_song(¤t_level); + levelintro(); + update_time = st_get_ticks(); + + fread(&score,sizeof(int),1,fi); + fread(&distros,sizeof(int),1,fi); + fread(&scroll_x,sizeof(float),1,fi); + fread(&tux,sizeof(player_type),1,fi); + timer_fread(&tux.invincible_timer,fi); + timer_fread(&tux.skidding_timer,fi); + timer_fread(&tux.safe_timer,fi); + timer_fread(&tux.frame_timer,fi); + timer_fread(&time_left,fi); + fread(&ui,sizeof(int),1,fi); + tux.hphysic.start_time += st_get_ticks() - ui; + tux.vphysic.start_time += st_get_ticks() - ui; + fclose(fi); + } + +} + +void slotinfo(char **pinfo, int slot) +{ + FILE* fi; + char slotfile[1024]; + char tmp[200]; + char str[5]; + int slot_level; + sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot); + + fi = fopen(slotfile, "rb"); + + sprintf(tmp,"Slot %d - ",slot); + + if (fi == NULL) + { + strcat(tmp,"Free"); + } + else + { + fgets(str, 100, fi); + str[strlen(str)-1] = '\0'; + strcat(tmp, str); + strcat(tmp, " / Level:"); + fread(&slot_level,sizeof(int),1,fi); + sprintf(str,"%d",slot_level); + strcat(tmp,str); + fclose(fi); + } + + *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1)); + strcpy(*pinfo,tmp); + +} + diff --git a/src/globals.c b/src/globals.c deleted file mode 100644 index d49c899c7..000000000 --- a/src/globals.c +++ /dev/null @@ -1,27 +0,0 @@ -// -// C Implementation: globals -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "globals.h" - -SDL_Surface * screen; -text_type black_text, gold_text, blue_text, red_text, yellow_nums, white_text, white_small_text, white_big_text; - -int use_gl, use_joystick, use_fullscreen, debug_mode, show_fps; - -/* SuperTux directory ($HOME/.supertux) and save directory($HOME/.supertux/save) */ -char *st_dir, *st_save_dir; - -#ifdef JOY_YES -SDL_Joystick * js; -#endif - - diff --git a/src/globals.cpp b/src/globals.cpp new file mode 100644 index 000000000..d49c899c7 --- /dev/null +++ b/src/globals.cpp @@ -0,0 +1,27 @@ +// +// C Implementation: globals +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "globals.h" + +SDL_Surface * screen; +text_type black_text, gold_text, blue_text, red_text, yellow_nums, white_text, white_small_text, white_big_text; + +int use_gl, use_joystick, use_fullscreen, debug_mode, show_fps; + +/* SuperTux directory ($HOME/.supertux) and save directory($HOME/.supertux/save) */ +char *st_dir, *st_save_dir; + +#ifdef JOY_YES +SDL_Joystick * js; +#endif + + diff --git a/src/high_scores.c b/src/high_scores.c deleted file mode 100644 index 741dc6227..000000000 --- a/src/high_scores.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - - by Adam Czachorowski - gislan@o2.pl - -*/ - -/* Open the highscore file: */ - -#include -#include - -#include "globals.h" -#include "high_scores.h" -#include "menu.h" -#include "screen.h" -#include "texture.h" - -int hs_score; -char hs_name[62]; /* highscores global variables*/ - -FILE * opendata(char * mode) -{ - char * filename = NULL; - FILE * fi; - - - filename = (char *) malloc(sizeof(char) * (strlen(st_dir) + - strlen("/st_highscore.dat") + 1)); - - strcpy(filename, st_dir); - /* Open the high score file: */ - -#ifdef LINUX - - strcat(filename, "/highscore"); -#else -#ifdef WIN32 - - strcat(filename, "/st_highscore.dat"); -#endif -#endif - - - /* Try opening the file: */ - - fi = fopen(filename, mode); - free( filename ); - - if (fi == NULL) - { - fprintf(stderr, "Warning: Unable to open the high score file "); - - if (strcmp(mode, "r") == 0) - fprintf(stderr, "for read!!!\n"); - else if (strcmp(mode, "w") == 0) - fprintf(stderr, "for write!!!\n"); - - } - - return(fi); -} - -/* Load data from high score file: */ - -void load_hs(void) -{ - FILE * fi; - char temp[128]; - int c, i, strl; - - hs_score = 100; - strcpy(hs_name, "Grandma\0"); - c = 0; - - /* Try to open file: */ - - fi = opendata("r"); - if (fi != NULL) - { - do - { - fgets(temp, sizeof(temp), fi); - - if (!feof(fi)) - { - temp[strlen(temp) - 1] = '\0'; - - - /* Parse each line: */ - - if (strstr(temp, "highscore=") == temp) - { - hs_score = atoi(temp + 10); - - if (hs_score == 0) - hs_score = 100; - } - if (strstr(temp, "name=") == temp) - { - fprintf(stderr, "name found\n"); - strl = strlen("name="); - for(c = strl, i = 0; c < strlen(temp); ++c, ++i) - hs_name[i] = temp[c]; - hs_name[i]= '\0'; - } - } - } - while (!feof(fi)); - - fclose(fi); - } -} - -void save_hs(int score) -{ - char str[80]; - - texture_type bkgd; - SDL_Event event; - FILE * fi; - - - texture_load(&bkgd, DATA_PREFIX "/images/highscore/highscore.png", IGNORE_ALPHA); - - hs_score = score; - - menu_reset(); - menu_set_current(&highscore_menu); - - if(!highscore_menu.item[0].input) - highscore_menu.item[0].input = (char*) malloc(strlen(hs_name) + 1); - - strcpy(highscore_menu.item[0].input,hs_name); - - /* ask for player's name */ - show_menu = 1; - while(show_menu) - { - texture_draw_bg(&bkgd, NO_UPDATE); - - text_drawf(&blue_text, "Congratulations", 0, 130, A_HMIDDLE, A_TOP, 2, NO_UPDATE); - text_draw(&blue_text, "Your score:", 150, 180, 1, NO_UPDATE); - sprintf(str, "%d", hs_score); - text_draw(&yellow_nums, str, 350, 170, 1, NO_UPDATE); - - menu_process_current(); - flipscreen(); - - while(SDL_PollEvent(&event)) - if(event.type == SDL_KEYDOWN) - menu_event(&event.key.keysym); - - switch (menu_check(&highscore_menu)) - { - case 0: - if(highscore_menu.item[0].input != NULL) - strcpy(hs_name, highscore_menu.item[0].input); - break; - } - - SDL_Delay(25); - } - - - /* Try to open file: */ - - fi = opendata("w"); - if (fi != NULL) - { - fprintf(fi, "# Supertux highscore file\n\n"); - - fprintf(fi, "name=%s\n", hs_name); - fprintf(fi, "highscore=%d\n", hs_score); - - fprintf(fi, "# (File automatically created.)\n"); - - fclose(fi); - } -} diff --git a/src/high_scores.cpp b/src/high_scores.cpp new file mode 100644 index 000000000..741dc6227 --- /dev/null +++ b/src/high_scores.cpp @@ -0,0 +1,180 @@ +/* + + by Adam Czachorowski + gislan@o2.pl + +*/ + +/* Open the highscore file: */ + +#include +#include + +#include "globals.h" +#include "high_scores.h" +#include "menu.h" +#include "screen.h" +#include "texture.h" + +int hs_score; +char hs_name[62]; /* highscores global variables*/ + +FILE * opendata(char * mode) +{ + char * filename = NULL; + FILE * fi; + + + filename = (char *) malloc(sizeof(char) * (strlen(st_dir) + + strlen("/st_highscore.dat") + 1)); + + strcpy(filename, st_dir); + /* Open the high score file: */ + +#ifdef LINUX + + strcat(filename, "/highscore"); +#else +#ifdef WIN32 + + strcat(filename, "/st_highscore.dat"); +#endif +#endif + + + /* Try opening the file: */ + + fi = fopen(filename, mode); + free( filename ); + + if (fi == NULL) + { + fprintf(stderr, "Warning: Unable to open the high score file "); + + if (strcmp(mode, "r") == 0) + fprintf(stderr, "for read!!!\n"); + else if (strcmp(mode, "w") == 0) + fprintf(stderr, "for write!!!\n"); + + } + + return(fi); +} + +/* Load data from high score file: */ + +void load_hs(void) +{ + FILE * fi; + char temp[128]; + int c, i, strl; + + hs_score = 100; + strcpy(hs_name, "Grandma\0"); + c = 0; + + /* Try to open file: */ + + fi = opendata("r"); + if (fi != NULL) + { + do + { + fgets(temp, sizeof(temp), fi); + + if (!feof(fi)) + { + temp[strlen(temp) - 1] = '\0'; + + + /* Parse each line: */ + + if (strstr(temp, "highscore=") == temp) + { + hs_score = atoi(temp + 10); + + if (hs_score == 0) + hs_score = 100; + } + if (strstr(temp, "name=") == temp) + { + fprintf(stderr, "name found\n"); + strl = strlen("name="); + for(c = strl, i = 0; c < strlen(temp); ++c, ++i) + hs_name[i] = temp[c]; + hs_name[i]= '\0'; + } + } + } + while (!feof(fi)); + + fclose(fi); + } +} + +void save_hs(int score) +{ + char str[80]; + + texture_type bkgd; + SDL_Event event; + FILE * fi; + + + texture_load(&bkgd, DATA_PREFIX "/images/highscore/highscore.png", IGNORE_ALPHA); + + hs_score = score; + + menu_reset(); + menu_set_current(&highscore_menu); + + if(!highscore_menu.item[0].input) + highscore_menu.item[0].input = (char*) malloc(strlen(hs_name) + 1); + + strcpy(highscore_menu.item[0].input,hs_name); + + /* ask for player's name */ + show_menu = 1; + while(show_menu) + { + texture_draw_bg(&bkgd, NO_UPDATE); + + text_drawf(&blue_text, "Congratulations", 0, 130, A_HMIDDLE, A_TOP, 2, NO_UPDATE); + text_draw(&blue_text, "Your score:", 150, 180, 1, NO_UPDATE); + sprintf(str, "%d", hs_score); + text_draw(&yellow_nums, str, 350, 170, 1, NO_UPDATE); + + menu_process_current(); + flipscreen(); + + while(SDL_PollEvent(&event)) + if(event.type == SDL_KEYDOWN) + menu_event(&event.key.keysym); + + switch (menu_check(&highscore_menu)) + { + case 0: + if(highscore_menu.item[0].input != NULL) + strcpy(hs_name, highscore_menu.item[0].input); + break; + } + + SDL_Delay(25); + } + + + /* Try to open file: */ + + fi = opendata("w"); + if (fi != NULL) + { + fprintf(fi, "# Supertux highscore file\n\n"); + + fprintf(fi, "name=%s\n", hs_name); + fprintf(fi, "highscore=%d\n", hs_score); + + fprintf(fi, "# (File automatically created.)\n"); + + fclose(fi); + } +} diff --git a/src/intro.c b/src/intro.c deleted file mode 100644 index c608d807b..000000000 --- a/src/intro.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - intro.c - - Super Tux - Intro Screen - - by Bill Kendrick - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 11, 2000 - March 15, 2004 -*/ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef LINUX -#include -#include -#include -#endif - -#include "defines.h" -#include "globals.h" -#include "intro.h" -#include "screen.h" -#include "texture.h" -#include "timer.h" - -char * intro_text[] = { - "Tux and Gown were having a nice picnic..", - "when suddenly...", - "Gown is beamed away!!!", - "This looks like a job for ---" -}; - - -/* --- INTRO --- */ - -int intro(void) -{ - SDL_Event event; - texture_type bkgd, copter_squish, copter_stretch, beam, - gown_sit, gown_lookup, gown_upset, - tux_sit, tux_upset, tux_mad; - texture_type copter[2]; - SDL_Rect src, dest; - int done, i, quit, j, scene; - int * height, * height_speed; - timer_type timer; - - /* Load sprite images: */ - texture_load(&bkgd, DATA_PREFIX "/images/intro/intro.png", IGNORE_ALPHA); - texture_load(&gown_sit, DATA_PREFIX "/images/intro/gown-sit.png", USE_ALPHA); - texture_load(&gown_lookup, DATA_PREFIX "/images/intro/gown-lookup.png", USE_ALPHA); - texture_load(&gown_upset, DATA_PREFIX "/images/intro/gown-upset.png", USE_ALPHA); - texture_load(&tux_sit, DATA_PREFIX "/images/intro/tux-sit.png", USE_ALPHA); - texture_load(&tux_upset, DATA_PREFIX "/images/intro/tux-upset.png", USE_ALPHA); - texture_load(&tux_mad, DATA_PREFIX "/images/intro/tux-mad.png", USE_ALPHA); - texture_load(&copter[0], DATA_PREFIX "/images/intro/copter1.png", USE_ALPHA); - texture_load(&copter[1], DATA_PREFIX "/images/intro/copter2.png", USE_ALPHA); - texture_load(&copter_squish, DATA_PREFIX "/images/intro/copter-squish.png", USE_ALPHA); - texture_load(&copter_stretch, DATA_PREFIX "/images/intro/copter-stretch.png", USE_ALPHA); - texture_load(&beam, DATA_PREFIX "/images/intro/beam.png", USE_ALPHA); - - /* Allocate buffer for height array: */ - - height = (int*) malloc(sizeof(int) * (gown_upset.w)); - height_speed = (int*) malloc(sizeof(int) * (gown_upset.w)); - - - /* Initialize height arrays: */ - - for (j = 0; j < (gown_upset.w); j++) - { - height[j] = 400; - height_speed[j] = (rand() % 10) + 1; - } - - /* Display background: */ - - texture_draw_bg(&bkgd, UPDATE); - - /* Animation: */ - - done = 0; - quit = 0; - scene = 0; - i = 0; - - timer_init(&timer,NO); - timer_start(&timer,10000); - - while (timer_check(&timer) && !done && !quit) - { - - /* Handle events: */ - - while (SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - /* Quit event - quit: */ - - quit = 1; - } - else if (event.type == SDL_KEYDOWN) - { - /* Keypress - skip intro: */ - - done = 1; - } -#ifdef JOY_YES - else if (event.type == SDL_JOYBUTTONDOWN) - { - /* Fire button - skip intro: */ - - done = 1; - } -#endif - } - - - /* Display background: */ - - /* Draw things: */ - - if (timer_get_gone(&timer) < 2000 && scene == 0) - { - ++scene; - /* Gown and tux sitting: */ - - texture_draw(&tux_sit, 270, 400, UPDATE); - texture_draw(&gown_sit, 320, 400, UPDATE); - - text_drawf(&white_text, intro_text[0], 0, -8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); - } - - - if (timer_get_gone(&timer) >= 2000 && scene == 1) - { - ++scene; - /* Helicopter begins to fly in: */ - - erasecenteredtext(&white_text, intro_text[0], 454, &bkgd, NO_UPDATE, 1); - text_drawf(&white_text, intro_text[1], 0,-8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); - } - - - if (timer_get_gone(&timer) >= 2000 && timer_get_gone(&timer) < 4000) - { - /* Helicopter flying in: */ - texture_draw_part(&bkgd,0,32, 0, 32, screen->w, (copter[0].h), NO_UPDATE); - - texture_draw(&copter[i % 2], - (float)(timer_get_gone(&timer) - 2000) / 5 - (copter[0].w), 32, - NO_UPDATE); - - update_rect(screen, 0, 32, screen->w, (copter[0].h)); - } - - - if (timer_get_gone(&timer) >= 2500 && scene == 2) - { - ++scene; - /* Gown notices something... */ - - texture_draw(&gown_lookup, 320, 400, UPDATE); - } - - - if (timer_get_gone(&timer) >= 3500 && scene == 3) - { - ++scene; - /* Gown realizes it's bad! */ - - texture_draw(&gown_upset, 320, 400, UPDATE); - } - - - if (timer_get_gone(&timer) >= 4000 && timer_get_gone(&timer) < 8000) - { - /* Helicopter sits: */ - texture_draw_part(&bkgd,0,32, 0, 32, screen->w, (copter[0].h), NO_UPDATE); - - texture_draw(&copter[i % 2], 400 - (copter[0].w), 32, NO_UPDATE); - update_rect(screen, 0, 32, screen->w, (copter[0].h)); - } - - - if (timer_get_gone(&timer) >= 5000 && scene == 4) - { - ++scene; - /* Tux realizes something's happening: */ - - texture_draw(&tux_upset, 270, 400, UPDATE); - - - erasecenteredtext(&white_text, intro_text[1], 454, &bkgd, UPDATE, 1); - text_drawf(&white_text, intro_text[2], 0,-8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); - } - - - if (timer_get_gone(&timer) >= 5000 && timer_get_gone(&timer) <= 8000) - { - /* Beam gown up! */ - - texture_draw_part(&bkgd, - 310, 32 + (copter[0].h), 310, - 32 + (copter[0].h), - (gown_upset.w) + 20, - 376 + (gown_upset.h) - (copter[0].h), NO_UPDATE); - - - for (j = 0; j < (gown_upset.sdl_surface -> w); j++) - { - texture_draw(&beam, 320 + j - ((beam.w) / 2), height[j], - NO_UPDATE); - - src.x = j; - src.y = 0; - src.w = 1; - src.h = (gown_upset.h); - - dest.x = 320 + j; - dest.y = height[j]; - dest.w = src.w; - dest.h = src.h; - - texture_draw_part(&gown_upset,src.x,src.y,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); - - height[j] = 400 + rand() % 10 - (int)(300. * ((float)(timer_get_gone(&timer) - 5000)/(float)3000.)); - if(height[j] < 105) - height[j] = 105; - } - - update_rect(screen, - 310, - 32 + (copter[0].h), - (gown_upset.w) + 20, - 400 + (gown_upset.h) - (copter[0].h)); - } - - - if (timer_get_gone(&timer) >= 8000 && scene == 5) - { - texture_draw_part(&bkgd, - 310, 32 + (copter[0].h), 310, - 32 + (copter[0].h), - (gown_upset.w) + 20, - 368 + (gown_upset.h) - (copter[0].h), NO_UPDATE); - - ++scene; - /* Tux gets mad! */ - - texture_draw(&tux_mad, 270, 400, UPDATE); - - erasecenteredtext(&white_text, intro_text[2], 454, &bkgd, UPDATE, 1); - text_drawf(&white_text, intro_text[3], 0,-8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); - } - - - if (timer_get_gone(&timer) >= 8000 && timer_get_gone(&timer) <= 8250) - { - /* Helicopter starting to speed off: */ - - texture_draw_part(&bkgd, 0, 32, 0, 32, screen->w, (copter_squish.h), NO_UPDATE); - - texture_draw(&copter_squish, - 400 - (copter[0].w), 32, - NO_UPDATE); - - update_rect(screen, 0, 32, screen->w, (copter_squish.h)); - } - - - if (timer_get_gone(&timer) >= 8250) - { - /* Helicopter speeding off: */ - - texture_draw_part(&bkgd, 0, 32, 0, 32, screen->w, (copter_stretch.h), NO_UPDATE); - - texture_draw(&copter_stretch, - (timer_get_gone(&timer) - 8250) /*(i - (8250 / FPS)) * 30*/ + 400 - (copter[0].w), - 32, - NO_UPDATE); - - update_rect(screen, 0, 32, screen->w, (copter_stretch.h)); - } - - flipscreen(); - - ++i; - /* Pause: */ - SDL_Delay(20); - } - - - /* Free surfaces: */ - - texture_free(&bkgd); - texture_free(&gown_sit); - texture_free(&gown_lookup); - texture_free(&gown_upset); - texture_free(&tux_sit); - texture_free(&tux_upset); - texture_free(&tux_mad); - texture_free(&copter[0]); - texture_free(&copter[1]); - texture_free(&copter_squish); - texture_free(&copter_stretch); - texture_free(&beam); - - - /* Free array buffers: */ - - free(height); - free(height_speed); - - - /* Return to main! */ - - return(quit); -} diff --git a/src/intro.cpp b/src/intro.cpp new file mode 100644 index 000000000..c608d807b --- /dev/null +++ b/src/intro.cpp @@ -0,0 +1,328 @@ +/* + intro.c + + Super Tux - Intro Screen + + by Bill Kendrick + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 11, 2000 - March 15, 2004 +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef LINUX +#include +#include +#include +#endif + +#include "defines.h" +#include "globals.h" +#include "intro.h" +#include "screen.h" +#include "texture.h" +#include "timer.h" + +char * intro_text[] = { + "Tux and Gown were having a nice picnic..", + "when suddenly...", + "Gown is beamed away!!!", + "This looks like a job for ---" +}; + + +/* --- INTRO --- */ + +int intro(void) +{ + SDL_Event event; + texture_type bkgd, copter_squish, copter_stretch, beam, + gown_sit, gown_lookup, gown_upset, + tux_sit, tux_upset, tux_mad; + texture_type copter[2]; + SDL_Rect src, dest; + int done, i, quit, j, scene; + int * height, * height_speed; + timer_type timer; + + /* Load sprite images: */ + texture_load(&bkgd, DATA_PREFIX "/images/intro/intro.png", IGNORE_ALPHA); + texture_load(&gown_sit, DATA_PREFIX "/images/intro/gown-sit.png", USE_ALPHA); + texture_load(&gown_lookup, DATA_PREFIX "/images/intro/gown-lookup.png", USE_ALPHA); + texture_load(&gown_upset, DATA_PREFIX "/images/intro/gown-upset.png", USE_ALPHA); + texture_load(&tux_sit, DATA_PREFIX "/images/intro/tux-sit.png", USE_ALPHA); + texture_load(&tux_upset, DATA_PREFIX "/images/intro/tux-upset.png", USE_ALPHA); + texture_load(&tux_mad, DATA_PREFIX "/images/intro/tux-mad.png", USE_ALPHA); + texture_load(&copter[0], DATA_PREFIX "/images/intro/copter1.png", USE_ALPHA); + texture_load(&copter[1], DATA_PREFIX "/images/intro/copter2.png", USE_ALPHA); + texture_load(&copter_squish, DATA_PREFIX "/images/intro/copter-squish.png", USE_ALPHA); + texture_load(&copter_stretch, DATA_PREFIX "/images/intro/copter-stretch.png", USE_ALPHA); + texture_load(&beam, DATA_PREFIX "/images/intro/beam.png", USE_ALPHA); + + /* Allocate buffer for height array: */ + + height = (int*) malloc(sizeof(int) * (gown_upset.w)); + height_speed = (int*) malloc(sizeof(int) * (gown_upset.w)); + + + /* Initialize height arrays: */ + + for (j = 0; j < (gown_upset.w); j++) + { + height[j] = 400; + height_speed[j] = (rand() % 10) + 1; + } + + /* Display background: */ + + texture_draw_bg(&bkgd, UPDATE); + + /* Animation: */ + + done = 0; + quit = 0; + scene = 0; + i = 0; + + timer_init(&timer,NO); + timer_start(&timer,10000); + + while (timer_check(&timer) && !done && !quit) + { + + /* Handle events: */ + + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + /* Quit event - quit: */ + + quit = 1; + } + else if (event.type == SDL_KEYDOWN) + { + /* Keypress - skip intro: */ + + done = 1; + } +#ifdef JOY_YES + else if (event.type == SDL_JOYBUTTONDOWN) + { + /* Fire button - skip intro: */ + + done = 1; + } +#endif + } + + + /* Display background: */ + + /* Draw things: */ + + if (timer_get_gone(&timer) < 2000 && scene == 0) + { + ++scene; + /* Gown and tux sitting: */ + + texture_draw(&tux_sit, 270, 400, UPDATE); + texture_draw(&gown_sit, 320, 400, UPDATE); + + text_drawf(&white_text, intro_text[0], 0, -8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); + } + + + if (timer_get_gone(&timer) >= 2000 && scene == 1) + { + ++scene; + /* Helicopter begins to fly in: */ + + erasecenteredtext(&white_text, intro_text[0], 454, &bkgd, NO_UPDATE, 1); + text_drawf(&white_text, intro_text[1], 0,-8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); + } + + + if (timer_get_gone(&timer) >= 2000 && timer_get_gone(&timer) < 4000) + { + /* Helicopter flying in: */ + texture_draw_part(&bkgd,0,32, 0, 32, screen->w, (copter[0].h), NO_UPDATE); + + texture_draw(&copter[i % 2], + (float)(timer_get_gone(&timer) - 2000) / 5 - (copter[0].w), 32, + NO_UPDATE); + + update_rect(screen, 0, 32, screen->w, (copter[0].h)); + } + + + if (timer_get_gone(&timer) >= 2500 && scene == 2) + { + ++scene; + /* Gown notices something... */ + + texture_draw(&gown_lookup, 320, 400, UPDATE); + } + + + if (timer_get_gone(&timer) >= 3500 && scene == 3) + { + ++scene; + /* Gown realizes it's bad! */ + + texture_draw(&gown_upset, 320, 400, UPDATE); + } + + + if (timer_get_gone(&timer) >= 4000 && timer_get_gone(&timer) < 8000) + { + /* Helicopter sits: */ + texture_draw_part(&bkgd,0,32, 0, 32, screen->w, (copter[0].h), NO_UPDATE); + + texture_draw(&copter[i % 2], 400 - (copter[0].w), 32, NO_UPDATE); + update_rect(screen, 0, 32, screen->w, (copter[0].h)); + } + + + if (timer_get_gone(&timer) >= 5000 && scene == 4) + { + ++scene; + /* Tux realizes something's happening: */ + + texture_draw(&tux_upset, 270, 400, UPDATE); + + + erasecenteredtext(&white_text, intro_text[1], 454, &bkgd, UPDATE, 1); + text_drawf(&white_text, intro_text[2], 0,-8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); + } + + + if (timer_get_gone(&timer) >= 5000 && timer_get_gone(&timer) <= 8000) + { + /* Beam gown up! */ + + texture_draw_part(&bkgd, + 310, 32 + (copter[0].h), 310, + 32 + (copter[0].h), + (gown_upset.w) + 20, + 376 + (gown_upset.h) - (copter[0].h), NO_UPDATE); + + + for (j = 0; j < (gown_upset.sdl_surface -> w); j++) + { + texture_draw(&beam, 320 + j - ((beam.w) / 2), height[j], + NO_UPDATE); + + src.x = j; + src.y = 0; + src.w = 1; + src.h = (gown_upset.h); + + dest.x = 320 + j; + dest.y = height[j]; + dest.w = src.w; + dest.h = src.h; + + texture_draw_part(&gown_upset,src.x,src.y,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); + + height[j] = 400 + rand() % 10 - (int)(300. * ((float)(timer_get_gone(&timer) - 5000)/(float)3000.)); + if(height[j] < 105) + height[j] = 105; + } + + update_rect(screen, + 310, + 32 + (copter[0].h), + (gown_upset.w) + 20, + 400 + (gown_upset.h) - (copter[0].h)); + } + + + if (timer_get_gone(&timer) >= 8000 && scene == 5) + { + texture_draw_part(&bkgd, + 310, 32 + (copter[0].h), 310, + 32 + (copter[0].h), + (gown_upset.w) + 20, + 368 + (gown_upset.h) - (copter[0].h), NO_UPDATE); + + ++scene; + /* Tux gets mad! */ + + texture_draw(&tux_mad, 270, 400, UPDATE); + + erasecenteredtext(&white_text, intro_text[2], 454, &bkgd, UPDATE, 1); + text_drawf(&white_text, intro_text[3], 0,-8, A_HMIDDLE, A_BOTTOM, 0, NO_UPDATE); + } + + + if (timer_get_gone(&timer) >= 8000 && timer_get_gone(&timer) <= 8250) + { + /* Helicopter starting to speed off: */ + + texture_draw_part(&bkgd, 0, 32, 0, 32, screen->w, (copter_squish.h), NO_UPDATE); + + texture_draw(&copter_squish, + 400 - (copter[0].w), 32, + NO_UPDATE); + + update_rect(screen, 0, 32, screen->w, (copter_squish.h)); + } + + + if (timer_get_gone(&timer) >= 8250) + { + /* Helicopter speeding off: */ + + texture_draw_part(&bkgd, 0, 32, 0, 32, screen->w, (copter_stretch.h), NO_UPDATE); + + texture_draw(&copter_stretch, + (timer_get_gone(&timer) - 8250) /*(i - (8250 / FPS)) * 30*/ + 400 - (copter[0].w), + 32, + NO_UPDATE); + + update_rect(screen, 0, 32, screen->w, (copter_stretch.h)); + } + + flipscreen(); + + ++i; + /* Pause: */ + SDL_Delay(20); + } + + + /* Free surfaces: */ + + texture_free(&bkgd); + texture_free(&gown_sit); + texture_free(&gown_lookup); + texture_free(&gown_upset); + texture_free(&tux_sit); + texture_free(&tux_upset); + texture_free(&tux_mad); + texture_free(&copter[0]); + texture_free(&copter[1]); + texture_free(&copter_squish); + texture_free(&copter_stretch); + texture_free(&beam); + + + /* Free array buffers: */ + + free(height); + free(height_speed); + + + /* Return to main! */ + + return(quit); +} diff --git a/src/level.c b/src/level.c deleted file mode 100644 index de04dd32a..000000000 --- a/src/level.c +++ /dev/null @@ -1,441 +0,0 @@ -// -// C Implementation: level -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2003 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include -#include -#include -#include "globals.h" -#include "setup.h" -#include "screen.h" -#include "level.h" -#include "physic.h" -#include "scene.h" - -texture_type img_bkgd, img_bkgd_tile[2][4], img_solid[4], img_brick[2]; - -void subset_init(st_subset* st_subset) -{ - st_subset->title = NULL; - st_subset->description = NULL; - st_subset->name = NULL; - st_subset->levels = 0; -} - -void subset_load(st_subset* st_subset, char *subset) -{ - FILE* fi; - char filename[1024]; - char str[1024]; - int len,i; - - st_subset->name = (char*) malloc(sizeof(char)*(strlen(subset)+1)); - strcpy(st_subset->name,subset); - - snprintf(filename, 1024, "%s/levels/%s/info", st_dir, subset); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/info", DATA_PREFIX, subset); - if(faccessible(filename)) - { - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - } - - /* Load title info: */ - fgets(str, 40, fi); - st_subset->title = (char*) malloc(sizeof(char)*(strlen(str)+1)); - strcpy(st_subset->title, str); - - /* Load the description: */ - - str[0] = '\0'; - st_subset->description = NULL; - len = 0; - while(fgets(str, 300, fi) != NULL) - { - len += strlen(str); - if(st_subset->description == NULL) - st_subset->description = (char*) calloc(len+1,sizeof(char)); - else - st_subset->description = (char*) realloc(st_subset->description, sizeof(char) * (len+1)); - strcat(st_subset->description,str); - } - fclose(fi); - - snprintf(str, 1024, "%s.png", filename); - if(faccessible(str)) - { - texture_load(&st_subset->image,str,IGNORE_ALPHA); - } - else - { - snprintf(filename, 1024, "%s/images/status/level-subset-info.png", DATA_PREFIX); - texture_load(&st_subset->image,filename,IGNORE_ALPHA); - } - } - - for(i=1; i != -1; ++i) - { - /* Get the number of levels in this subset */ - snprintf(filename, 1024, "%s/levels/%s/level%d.dat", st_dir, subset,i); - if(!faccessible(filename)) - { - snprintf(filename, 1024, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset,i); - if(!faccessible(filename)) - break; - } - } - st_subset->levels = --i; -} - -void subset_save(st_subset* st_subset) -{ - FILE* fi; - char filename[1024]; - - /* Save data file: */ - sprintf(filename, "/levels/%s/", st_subset->name); - - fcreatedir(filename); - snprintf(filename, 1024, "%s/levels/%s/info", st_dir, st_subset->name); - if(!fwriteable(filename)) - snprintf(filename, 1024, "%s/levels/%s/info", DATA_PREFIX, st_subset->name); - if(fwriteable(filename)) - { - fi = fopen(filename, "w"); - if (fi == NULL) - { - perror(filename); - } - - /* Save title info: */ - fputs(st_subset->title, fi); - fputs("\n", fi); - - /* Save the description: */ - - fputs(st_subset->description, fi); - fputs("\n", fi); - fclose(fi); - - } -} - -void subset_free(st_subset* st_subset) -{ - free(st_subset->title); - free(st_subset->description); - free(st_subset->name); - texture_free(&st_subset->image); - st_subset->levels = 0; -} - -/* Load data for this level: */ -/* Returns -1, if the loading of the level failed. */ -int level_load(st_level* plevel, char *subset, int level) -{ - int y,x; - FILE * fi; - char str[80]; - char filename[1024]; - char * line; - - /* Load data file: */ - - snprintf(filename, 1024, "%s/levels/%s/level%d.dat", st_dir, subset, level); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset, level); - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - return -1; - } - - - /* Load header info: */ - - - /* (Level title) */ - fgets(str, 20, fi); - strcpy(plevel->name, str); - plevel->name[strlen(plevel->name)-1] = '\0'; - - /* (Level theme) */ - fgets(str, 20, fi); - strcpy(plevel->theme, str); - plevel->theme[strlen(plevel->theme)-1] = '\0'; - - - - /* (Time to beat level) */ - fgets(str, 10, fi); - plevel->time_left = atoi(str); - - /* (Song file for this level) */ - fgets(str, sizeof(plevel->song_title), fi); - strcpy(plevel->song_title, str); - plevel->song_title[strlen(plevel->song_title)-1] = '\0'; - - /* (Level background image) */ - fgets(str, sizeof(plevel->bkgd_image), fi); - strcpy(plevel->bkgd_image, str); - plevel->bkgd_image[strlen(plevel->bkgd_image)-1] = '\0'; - - /* (Level background color) */ - fgets(str, 10, fi); - plevel->bkgd_red = atoi(str); - fgets(str, 10, fi); - plevel->bkgd_green= atoi(str); - fgets(str, 10, fi); - plevel->bkgd_blue = atoi(str); - - /* (Level width) */ - fgets(str, 10, fi); - plevel->width = atoi(str); - - /* (Level gravity) */ - fgets(str, 10, fi); - plevel->gravity = atof(str); - - /* Set the global gravity to the latest loaded level's gravity */ - gravity = plevel->gravity; - - /* Allocate some space for the line-reading! */ - - line = (char *) malloc(sizeof(char) * (plevel->width + 5)); - if (line == NULL) - { - fprintf(stderr, "Couldn't allocate space to load level data!"); - fclose(fi); - return -1; - } - - - /* Load the level lines: */ - - for (y = 0; y < 15; y++) - { - if(fgets(line, plevel->width + 5, fi) == NULL) - { - fprintf(stderr, "Level %s isn't complete!\n",plevel->name); - free(line); - fclose(fi); - return -1; - } - line[strlen(line) - 1] = '\0'; - plevel->tiles[y] = (unsigned char*) strdup(line); - } - - /* Mark the end position of this level! - Is a bit wrong here thought */ - - for (y = 0; y < 15; ++y) - { - for (x = 0; x < plevel->width; ++x) - { - if(plevel->tiles[y][x] == '|') - { - if(x*32 > endpos) - endpos = x*32; - } - } - } - - free(line); - fclose(fi); - return 0; -} - -/* Save data for level: */ - -void level_save(st_level* plevel, char * subset, int level) -{ - FILE * fi; - char filename[1024]; - int y; - char str[80]; - - /* Save data file: */ - sprintf(str, "/levels/%s/", subset); - fcreatedir(str); - snprintf(filename, 1024, "%s/levels/%s/level%d.dat", st_dir, subset, level); - if(!fwriteable(filename)) - snprintf(filename, 1024, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset, level); - - fi = fopen(filename, "w"); - if (fi == NULL) - { - perror(filename); - st_shutdown(); - exit(-1); - } - - fputs(plevel->name, fi); - fputs("\n", fi); - fputs(plevel->theme, fi); - fputs("\n", fi); - sprintf(str, "%d\n", plevel->time_left); /* time */ - fputs(str, fi); - fputs(plevel->song_title, fi); /* song filename */ - fputs("\n",fi); - fputs(plevel->bkgd_image, fi); /* background image */ - sprintf(str, "\n%d\n", plevel->bkgd_red); /* red background color */ - fputs(str, fi); - sprintf(str, "%d\n", plevel->bkgd_green); /* green background color */ - fputs(str, fi); - sprintf(str, "%d\n", plevel->bkgd_blue); /* blue background color */ - fputs(str, fi); - sprintf(str, "%d\n", plevel->width); /* level width */ - fputs(str, fi); - sprintf(str, "%2.1f\n", plevel->gravity); /* level gravity */ - fputs(str, fi); - - for(y = 0; y < 15; ++y) - { - fputs((const char*)plevel->tiles[y], fi); - fputs("\n", fi); - } - - fclose(fi); -} - - -/* Unload data for this level: */ - -void level_free(st_level* plevel) -{ - int i; - for(i=0; i < 15; ++i) - free(plevel->tiles[i]); - - plevel->name[0] = '\0'; - plevel->theme[0] = '\0'; - plevel->song_title[0] = '\0'; - plevel->bkgd_image[0] = '\0'; -} - -/* Load graphics: */ - -void level_load_gfx(st_level *plevel) -{ - level_load_image(&img_brick[0],plevel->theme,"brick0.png", IGNORE_ALPHA); - level_load_image(&img_brick[1],plevel->theme,"brick1.png", IGNORE_ALPHA); - - level_load_image(&img_solid[0],plevel->theme,"solid0.png", USE_ALPHA); - level_load_image(&img_solid[1],plevel->theme,"solid1.png", USE_ALPHA); - level_load_image(&img_solid[2],plevel->theme,"solid2.png", USE_ALPHA); - level_load_image(&img_solid[3],plevel->theme,"solid3.png", USE_ALPHA); - - level_load_image(&img_bkgd_tile[0][0],plevel->theme,"bkgd-00.png", USE_ALPHA); - level_load_image(&img_bkgd_tile[0][1],plevel->theme,"bkgd-01.png", USE_ALPHA); - level_load_image(&img_bkgd_tile[0][2],plevel->theme,"bkgd-02.png", USE_ALPHA); - level_load_image(&img_bkgd_tile[0][3],plevel->theme,"bkgd-03.png", USE_ALPHA); - - level_load_image(&img_bkgd_tile[1][0],plevel->theme,"bkgd-10.png", USE_ALPHA); - level_load_image(&img_bkgd_tile[1][1],plevel->theme,"bkgd-11.png", USE_ALPHA); - level_load_image(&img_bkgd_tile[1][2],plevel->theme,"bkgd-12.png", USE_ALPHA); - level_load_image(&img_bkgd_tile[1][3],plevel->theme,"bkgd-13.png", USE_ALPHA); - - if(strcmp(plevel->bkgd_image,"") != 0) - { - char fname[1024]; - snprintf(fname, 1024, "%s/background/%s", st_dir, plevel->bkgd_image); - if(!faccessible(fname)) - snprintf(fname, 1024, "%s/images/background/%s", DATA_PREFIX, plevel->bkgd_image); - texture_load(&img_bkgd, fname, IGNORE_ALPHA); - } - else - { - /* Quick hack to make sure an image is loaded, when we are freeing it afterwards. */# - level_load_image(&img_bkgd, plevel->theme,"solid0.png", IGNORE_ALPHA); - } -} - -/* Free graphics data for this level: */ - -void level_free_gfx(void) -{ - int i; - - for (i = 0; i < 2; i++) - { - texture_free(&img_brick[i]); - } - for (i = 0; i < 4; i++) - { - texture_free(&img_solid[i]); - texture_free(&img_bkgd_tile[0][i]); - texture_free(&img_bkgd_tile[1][i]); - } - - texture_free(&img_bkgd); -} - -/* Load a level-specific graphic... */ - -void level_load_image(texture_type* ptexture, char* theme, char * file, int use_alpha) -{ - char fname[1024]; - - snprintf(fname, 1024, "%s/themes/%s/%s", st_dir, theme, file); - if(!faccessible(fname)) - snprintf(fname, 1024, "%s/images/themes/%s/%s", DATA_PREFIX, theme, file); - - texture_load(ptexture, fname, use_alpha); -} - -/* Edit a piece of the map! */ - -void level_change(st_level* plevel, float x, float y, unsigned char c) -{ - int xx, yy; - - yy = ((int)y / 32); - xx = ((int)x / 32); - - if (yy >= 0 && yy < 15 && xx >= 0 && xx <= plevel->width) - plevel->tiles[yy][xx] = c; -} - -/* Free music data for this level: */ - -void level_free_song(void) -{ - free_music(level_song); - free_music(level_song_fast); -} - -/* Load music: */ - -void level_load_song(st_level* plevel) -{ - - char * song_path; - char * song_subtitle; - - song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + - strlen(plevel->song_title) + 8)); - sprintf(song_path, "%s/music/%s", DATA_PREFIX, plevel->song_title); - level_song = load_song(song_path); - free(song_path); - - - song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + - strlen(plevel->song_title) + 8 + 5)); - song_subtitle = strdup(plevel->song_title); - strcpy(strstr(song_subtitle, "."), "\0"); - sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(plevel->song_title, ".")); - level_song_fast = load_song(song_path); - free(song_subtitle); - free(song_path); -} diff --git a/src/level.cpp b/src/level.cpp new file mode 100644 index 000000000..de04dd32a --- /dev/null +++ b/src/level.cpp @@ -0,0 +1,441 @@ +// +// C Implementation: level +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2003 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include +#include +#include "globals.h" +#include "setup.h" +#include "screen.h" +#include "level.h" +#include "physic.h" +#include "scene.h" + +texture_type img_bkgd, img_bkgd_tile[2][4], img_solid[4], img_brick[2]; + +void subset_init(st_subset* st_subset) +{ + st_subset->title = NULL; + st_subset->description = NULL; + st_subset->name = NULL; + st_subset->levels = 0; +} + +void subset_load(st_subset* st_subset, char *subset) +{ + FILE* fi; + char filename[1024]; + char str[1024]; + int len,i; + + st_subset->name = (char*) malloc(sizeof(char)*(strlen(subset)+1)); + strcpy(st_subset->name,subset); + + snprintf(filename, 1024, "%s/levels/%s/info", st_dir, subset); + if(!faccessible(filename)) + snprintf(filename, 1024, "%s/levels/%s/info", DATA_PREFIX, subset); + if(faccessible(filename)) + { + fi = fopen(filename, "r"); + if (fi == NULL) + { + perror(filename); + } + + /* Load title info: */ + fgets(str, 40, fi); + st_subset->title = (char*) malloc(sizeof(char)*(strlen(str)+1)); + strcpy(st_subset->title, str); + + /* Load the description: */ + + str[0] = '\0'; + st_subset->description = NULL; + len = 0; + while(fgets(str, 300, fi) != NULL) + { + len += strlen(str); + if(st_subset->description == NULL) + st_subset->description = (char*) calloc(len+1,sizeof(char)); + else + st_subset->description = (char*) realloc(st_subset->description, sizeof(char) * (len+1)); + strcat(st_subset->description,str); + } + fclose(fi); + + snprintf(str, 1024, "%s.png", filename); + if(faccessible(str)) + { + texture_load(&st_subset->image,str,IGNORE_ALPHA); + } + else + { + snprintf(filename, 1024, "%s/images/status/level-subset-info.png", DATA_PREFIX); + texture_load(&st_subset->image,filename,IGNORE_ALPHA); + } + } + + for(i=1; i != -1; ++i) + { + /* Get the number of levels in this subset */ + snprintf(filename, 1024, "%s/levels/%s/level%d.dat", st_dir, subset,i); + if(!faccessible(filename)) + { + snprintf(filename, 1024, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset,i); + if(!faccessible(filename)) + break; + } + } + st_subset->levels = --i; +} + +void subset_save(st_subset* st_subset) +{ + FILE* fi; + char filename[1024]; + + /* Save data file: */ + sprintf(filename, "/levels/%s/", st_subset->name); + + fcreatedir(filename); + snprintf(filename, 1024, "%s/levels/%s/info", st_dir, st_subset->name); + if(!fwriteable(filename)) + snprintf(filename, 1024, "%s/levels/%s/info", DATA_PREFIX, st_subset->name); + if(fwriteable(filename)) + { + fi = fopen(filename, "w"); + if (fi == NULL) + { + perror(filename); + } + + /* Save title info: */ + fputs(st_subset->title, fi); + fputs("\n", fi); + + /* Save the description: */ + + fputs(st_subset->description, fi); + fputs("\n", fi); + fclose(fi); + + } +} + +void subset_free(st_subset* st_subset) +{ + free(st_subset->title); + free(st_subset->description); + free(st_subset->name); + texture_free(&st_subset->image); + st_subset->levels = 0; +} + +/* Load data for this level: */ +/* Returns -1, if the loading of the level failed. */ +int level_load(st_level* plevel, char *subset, int level) +{ + int y,x; + FILE * fi; + char str[80]; + char filename[1024]; + char * line; + + /* Load data file: */ + + snprintf(filename, 1024, "%s/levels/%s/level%d.dat", st_dir, subset, level); + if(!faccessible(filename)) + snprintf(filename, 1024, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset, level); + fi = fopen(filename, "r"); + if (fi == NULL) + { + perror(filename); + return -1; + } + + + /* Load header info: */ + + + /* (Level title) */ + fgets(str, 20, fi); + strcpy(plevel->name, str); + plevel->name[strlen(plevel->name)-1] = '\0'; + + /* (Level theme) */ + fgets(str, 20, fi); + strcpy(plevel->theme, str); + plevel->theme[strlen(plevel->theme)-1] = '\0'; + + + + /* (Time to beat level) */ + fgets(str, 10, fi); + plevel->time_left = atoi(str); + + /* (Song file for this level) */ + fgets(str, sizeof(plevel->song_title), fi); + strcpy(plevel->song_title, str); + plevel->song_title[strlen(plevel->song_title)-1] = '\0'; + + /* (Level background image) */ + fgets(str, sizeof(plevel->bkgd_image), fi); + strcpy(plevel->bkgd_image, str); + plevel->bkgd_image[strlen(plevel->bkgd_image)-1] = '\0'; + + /* (Level background color) */ + fgets(str, 10, fi); + plevel->bkgd_red = atoi(str); + fgets(str, 10, fi); + plevel->bkgd_green= atoi(str); + fgets(str, 10, fi); + plevel->bkgd_blue = atoi(str); + + /* (Level width) */ + fgets(str, 10, fi); + plevel->width = atoi(str); + + /* (Level gravity) */ + fgets(str, 10, fi); + plevel->gravity = atof(str); + + /* Set the global gravity to the latest loaded level's gravity */ + gravity = plevel->gravity; + + /* Allocate some space for the line-reading! */ + + line = (char *) malloc(sizeof(char) * (plevel->width + 5)); + if (line == NULL) + { + fprintf(stderr, "Couldn't allocate space to load level data!"); + fclose(fi); + return -1; + } + + + /* Load the level lines: */ + + for (y = 0; y < 15; y++) + { + if(fgets(line, plevel->width + 5, fi) == NULL) + { + fprintf(stderr, "Level %s isn't complete!\n",plevel->name); + free(line); + fclose(fi); + return -1; + } + line[strlen(line) - 1] = '\0'; + plevel->tiles[y] = (unsigned char*) strdup(line); + } + + /* Mark the end position of this level! - Is a bit wrong here thought */ + + for (y = 0; y < 15; ++y) + { + for (x = 0; x < plevel->width; ++x) + { + if(plevel->tiles[y][x] == '|') + { + if(x*32 > endpos) + endpos = x*32; + } + } + } + + free(line); + fclose(fi); + return 0; +} + +/* Save data for level: */ + +void level_save(st_level* plevel, char * subset, int level) +{ + FILE * fi; + char filename[1024]; + int y; + char str[80]; + + /* Save data file: */ + sprintf(str, "/levels/%s/", subset); + fcreatedir(str); + snprintf(filename, 1024, "%s/levels/%s/level%d.dat", st_dir, subset, level); + if(!fwriteable(filename)) + snprintf(filename, 1024, "%s/levels/%s/level%d.dat", DATA_PREFIX, subset, level); + + fi = fopen(filename, "w"); + if (fi == NULL) + { + perror(filename); + st_shutdown(); + exit(-1); + } + + fputs(plevel->name, fi); + fputs("\n", fi); + fputs(plevel->theme, fi); + fputs("\n", fi); + sprintf(str, "%d\n", plevel->time_left); /* time */ + fputs(str, fi); + fputs(plevel->song_title, fi); /* song filename */ + fputs("\n",fi); + fputs(plevel->bkgd_image, fi); /* background image */ + sprintf(str, "\n%d\n", plevel->bkgd_red); /* red background color */ + fputs(str, fi); + sprintf(str, "%d\n", plevel->bkgd_green); /* green background color */ + fputs(str, fi); + sprintf(str, "%d\n", plevel->bkgd_blue); /* blue background color */ + fputs(str, fi); + sprintf(str, "%d\n", plevel->width); /* level width */ + fputs(str, fi); + sprintf(str, "%2.1f\n", plevel->gravity); /* level gravity */ + fputs(str, fi); + + for(y = 0; y < 15; ++y) + { + fputs((const char*)plevel->tiles[y], fi); + fputs("\n", fi); + } + + fclose(fi); +} + + +/* Unload data for this level: */ + +void level_free(st_level* plevel) +{ + int i; + for(i=0; i < 15; ++i) + free(plevel->tiles[i]); + + plevel->name[0] = '\0'; + plevel->theme[0] = '\0'; + plevel->song_title[0] = '\0'; + plevel->bkgd_image[0] = '\0'; +} + +/* Load graphics: */ + +void level_load_gfx(st_level *plevel) +{ + level_load_image(&img_brick[0],plevel->theme,"brick0.png", IGNORE_ALPHA); + level_load_image(&img_brick[1],plevel->theme,"brick1.png", IGNORE_ALPHA); + + level_load_image(&img_solid[0],plevel->theme,"solid0.png", USE_ALPHA); + level_load_image(&img_solid[1],plevel->theme,"solid1.png", USE_ALPHA); + level_load_image(&img_solid[2],plevel->theme,"solid2.png", USE_ALPHA); + level_load_image(&img_solid[3],plevel->theme,"solid3.png", USE_ALPHA); + + level_load_image(&img_bkgd_tile[0][0],plevel->theme,"bkgd-00.png", USE_ALPHA); + level_load_image(&img_bkgd_tile[0][1],plevel->theme,"bkgd-01.png", USE_ALPHA); + level_load_image(&img_bkgd_tile[0][2],plevel->theme,"bkgd-02.png", USE_ALPHA); + level_load_image(&img_bkgd_tile[0][3],plevel->theme,"bkgd-03.png", USE_ALPHA); + + level_load_image(&img_bkgd_tile[1][0],plevel->theme,"bkgd-10.png", USE_ALPHA); + level_load_image(&img_bkgd_tile[1][1],plevel->theme,"bkgd-11.png", USE_ALPHA); + level_load_image(&img_bkgd_tile[1][2],plevel->theme,"bkgd-12.png", USE_ALPHA); + level_load_image(&img_bkgd_tile[1][3],plevel->theme,"bkgd-13.png", USE_ALPHA); + + if(strcmp(plevel->bkgd_image,"") != 0) + { + char fname[1024]; + snprintf(fname, 1024, "%s/background/%s", st_dir, plevel->bkgd_image); + if(!faccessible(fname)) + snprintf(fname, 1024, "%s/images/background/%s", DATA_PREFIX, plevel->bkgd_image); + texture_load(&img_bkgd, fname, IGNORE_ALPHA); + } + else + { + /* Quick hack to make sure an image is loaded, when we are freeing it afterwards. */# + level_load_image(&img_bkgd, plevel->theme,"solid0.png", IGNORE_ALPHA); + } +} + +/* Free graphics data for this level: */ + +void level_free_gfx(void) +{ + int i; + + for (i = 0; i < 2; i++) + { + texture_free(&img_brick[i]); + } + for (i = 0; i < 4; i++) + { + texture_free(&img_solid[i]); + texture_free(&img_bkgd_tile[0][i]); + texture_free(&img_bkgd_tile[1][i]); + } + + texture_free(&img_bkgd); +} + +/* Load a level-specific graphic... */ + +void level_load_image(texture_type* ptexture, char* theme, char * file, int use_alpha) +{ + char fname[1024]; + + snprintf(fname, 1024, "%s/themes/%s/%s", st_dir, theme, file); + if(!faccessible(fname)) + snprintf(fname, 1024, "%s/images/themes/%s/%s", DATA_PREFIX, theme, file); + + texture_load(ptexture, fname, use_alpha); +} + +/* Edit a piece of the map! */ + +void level_change(st_level* plevel, float x, float y, unsigned char c) +{ + int xx, yy; + + yy = ((int)y / 32); + xx = ((int)x / 32); + + if (yy >= 0 && yy < 15 && xx >= 0 && xx <= plevel->width) + plevel->tiles[yy][xx] = c; +} + +/* Free music data for this level: */ + +void level_free_song(void) +{ + free_music(level_song); + free_music(level_song_fast); +} + +/* Load music: */ + +void level_load_song(st_level* plevel) +{ + + char * song_path; + char * song_subtitle; + + song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + + strlen(plevel->song_title) + 8)); + sprintf(song_path, "%s/music/%s", DATA_PREFIX, plevel->song_title); + level_song = load_song(song_path); + free(song_path); + + + song_path = (char *) malloc(sizeof(char) * (strlen(DATA_PREFIX) + + strlen(plevel->song_title) + 8 + 5)); + song_subtitle = strdup(plevel->song_title); + strcpy(strstr(song_subtitle, "."), "\0"); + sprintf(song_path, "%s/music/%s-fast%s", DATA_PREFIX, song_subtitle, strstr(plevel->song_title, ".")); + level_song_fast = load_song(song_path); + free(song_subtitle); + free(song_path); +} diff --git a/src/leveleditor.c b/src/leveleditor.c deleted file mode 100644 index d0d7b9e13..000000000 --- a/src/leveleditor.c +++ /dev/null @@ -1,1517 +0,0 @@ -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ - -/* December 28, 2003 - March 15, 2004 */ - -/* leveleditor.c - A built-in level editor for SuperTux - Ricardo Cruz - Tobias Glaesser */ - -#include -#include -#include -#include -#include -#include -#include -#include "leveleditor.h" - -#include "screen.h" -#include "defines.h" -#include "globals.h" -#include "setup.h" -#include "menu.h" -#include "level.h" -#include "badguy.h" -#include "scene.h" -#include "button.h" - -/* definitions to aid development */ -#define DONE_LEVELEDITOR 1 -#define DONE_QUIT 2 -#define DONE_CHANGELEVEL 3 - -/* definitions that affect gameplay */ -#define KEY_CURSOR_SPEED 32 -#define KEY_CURSOR_FASTSPEED 64 - -/* when pagedown/up pressed speed:*/ -#define PAGE_CURSOR_SPEED 13*32 - -#define MOUSE_LEFT_MARGIN 80 -#define MOUSE_RIGHT_MARGIN (560-32) -/* right_margin should noticed that the cursor is 32 pixels, - so it should subtract that value */ -#define MOUSE_POS_SPEED 20 - -/* look */ -#define SELECT_W 2 // size of the selections lines -#define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A) - -/* gameloop funcs declerations */ - -void loadshared(void); -void unloadshared(void); - -/* own declerations */ -/* crutial ones (main loop) */ -int le_init(); -void le_quit(); -void le_drawlevel(); -void le_drawinterface(); -void le_checkevents(); -void le_change(float x, float y, unsigned char c); -void le_testlevel(); -void le_showhelp(); -void le_set_defaults(void); -void le_activate_bad_guys(void); -void le_new_subset(char *subset_name); - -void le_highlight_selection(); - -void apply_level_settings_menu(); -void update_subset_settings_menu(); -void save_subset_settings_menu(); -void le_update_buttons(char*); - -/* leveleditor internals */ -static string_list_type level_subsets; -static int le_level_changed; /* if changes, ask for saving, when quiting*/ -static int pos_x, cursor_x, cursor_y, cursor_tile, fire; -static int le_level; -static st_level* le_current_level; -static st_subset le_level_subset; -static int le_show_grid; -static int le_frame; -static texture_type le_selection; -static int done; -static char le_current_tile; -static int le_mouse_pressed[2]; -static button_type le_save_level_bt; -static button_type le_test_level_bt; -static button_type le_next_level_bt; -static button_type le_previous_level_bt; -static button_type le_move_right_bt; -static button_type le_move_left_bt; -static button_type le_rubber_bt; -static button_type le_select_mode_one_bt; -static button_type le_select_mode_two_bt; -static button_type le_settings_bt; -static button_type le_bad_bt; -static button_type le_bkgd_bt; -static button_type le_fgd_bt; -static button_panel_type le_bkgd_panel; -static button_panel_type le_fgd_panel; -static button_panel_type le_bad_panel; -static menu_type leveleditor_menu; -static menu_type subset_load_menu; -static menu_type subset_new_menu; -static menu_type subset_settings_menu; -static menu_type level_settings_menu; - -static square selection; -static int le_selection_mode; -static SDL_Event event; - -void le_activate_bad_guys(void) -{ - int x,y; - - /* Activate bad guys: */ - - /* as oposed to the gameloop.c func, this one doesn't remove - the badguys from tiles */ - - for (y = 0; y < 15; ++y) - for (x = 0; x < le_current_level->width; ++x) - if (le_current_level->tiles[y][x] >= '0' && le_current_level->tiles[y][x] <= '9') - add_bad_guy(x * 32, y * 32, le_current_level->tiles[y][x] - '0'); -} - -void le_set_defaults() -{ - if(le_current_level != NULL) - { - /* Set defaults: */ - - if(le_current_level->time_left == 0) - le_current_level->time_left = 255; - } -} - -int leveleditor(int levelnb) -{ - int last_time, now_time, i; - - le_level = levelnb; - if(le_init() != 0) - return 1; - - /* Clear screen: */ - - clearscreen(0, 0, 0); - updatescreen(); - - while (SDL_PollEvent(&event)) - {} - - while(YES) - { - last_time = SDL_GetTicks(); - le_frame++; - - le_checkevents(); - - if(le_current_level != NULL) - { - /* making events results to be in order */ - if(pos_x < 0) - pos_x = 0; - if(pos_x > (le_current_level->width * 32) - screen->w) - pos_x = (le_current_level->width * 32) - screen->w; - - /* draw the level */ - le_drawlevel(); - } - else - clearscreen(0, 0, 0); - - /* draw editor interface */ - le_drawinterface(); - - if(show_menu) - { - menu_process_current(); - if(current_menu == &leveleditor_menu) - { - switch (menu_check(&leveleditor_menu)) - { - case 2: - show_menu = NO; - break; - case 3: - update_subset_settings_menu(); - break; - case 7: - done = DONE_LEVELEDITOR; - break; - } - } - else if(current_menu == &level_settings_menu) - { - switch (menu_check(&level_settings_menu)) - { - case 13: - apply_level_settings_menu(); - menu_set_current(&leveleditor_menu); - break; - default: - show_menu = YES; - break; - } - } - else if(current_menu == &subset_load_menu) - { - switch (i = menu_check(&subset_load_menu)) - { - case 0: - break; - default: - if(i != -1) - { - subset_load(&le_level_subset,level_subsets.item[i-2]); - leveleditor_menu.item[3].kind = MN_GOTO; - le_level = 1; - arrays_init(); - loadshared(); - le_current_level = (st_level*) malloc(sizeof(st_level)); - if(level_load(le_current_level, le_level_subset.name, le_level) != 0) - { - le_quit(); - return 1; - } - le_update_buttons(le_current_level->theme); - le_set_defaults(); - level_load_gfx(le_current_level); - le_activate_bad_guys(); - show_menu = YES; - } - break; - } - } - else if(current_menu == &subset_new_menu) - { - if(subset_new_menu.item[2].input[0] == '\0') - subset_new_menu.item[3].kind = MN_DEACTIVE; - else - { - subset_new_menu.item[3].kind = MN_ACTION; - - switch (i = menu_check(&subset_new_menu)) - { - case 3: - le_new_subset(subset_new_menu.item[2].input); - subset_load(&le_level_subset,subset_new_menu.item[2].input); - leveleditor_menu.item[3].kind = MN_GOTO; - le_level = 1; - arrays_init(); - loadshared(); - le_current_level = (st_level*) malloc(sizeof(st_level)); - if(level_load(le_current_level, le_level_subset.name, le_level) != 0) - { - le_quit(); - return 1; - } - le_update_buttons(le_current_level->theme); - le_set_defaults(); - level_load_gfx(le_current_level); - le_activate_bad_guys(); - menu_item_change_input(&subset_new_menu.item[2],""); - show_menu = YES; - break; - } - } - } - else if(current_menu == &subset_settings_menu) - { - if(strcmp(le_level_subset.title,subset_settings_menu.item[2].input) == 0 && strcmp(le_level_subset.description,subset_settings_menu.item[3].input) == 0 ) - subset_settings_menu.item[5].kind = MN_DEACTIVE; - else - subset_settings_menu.item[5].kind = MN_ACTION; - - switch (i = menu_check(&subset_settings_menu)) - { - case 5: - save_subset_settings_menu(); - show_menu = YES; - break; - } - } - } - - if(done) - { - le_quit(); - return 0; - } - - if(done == DONE_QUIT) - { - le_quit(); - return 1; - } - - SDL_Delay(25); - now_time = SDL_GetTicks(); - if (now_time < last_time + FPS) - SDL_Delay(last_time + FPS - now_time); /* delay some time */ - - flipscreen(); - } - - return done; -} - -void le_default_level(st_level* plevel) -{ - int i,y; - strcpy(plevel->name,"UnNamed"); - strcpy(plevel->theme,"antarctica"); - strcpy(plevel->song_title,"Mortimers_chipdisko.mod"); - strcpy(plevel->bkgd_image,"arctis.png"); - plevel->width = 21; - plevel->time_left = 100; - plevel->gravity = 10.; - plevel->bkgd_red = 0; - plevel->bkgd_green = 0; - plevel->bkgd_blue = 0; - - for(i = 0; i < 15; ++i) - { - plevel->tiles[i] = (unsigned char*) malloc((plevel->width+1)*sizeof(unsigned char)); - plevel->tiles[i][plevel->width] = (unsigned char) '\0'; - for(y = 0; y < plevel->width; ++y) - plevel->tiles[i][y] = (unsigned char) '.'; - plevel->tiles[i][plevel->width] = (unsigned char) '\0'; - } -} - -void le_new_subset(char *subset_name) -{ - st_level new_lev; - st_subset new_subset; - new_subset.name = (char*) malloc((strlen(subset_name)+1)*sizeof(char)); - strcpy(new_subset.name,subset_name); - new_subset.title = (char*) malloc((strlen("Unknown Title")+1)*sizeof(char)); - strcpy(new_subset.title,"Unknown Title"); - new_subset.description = (char*) malloc((strlen("No description so far.")+1)*sizeof(char)); - strcpy(new_subset.description,"No description so far."); - subset_save(&new_subset); - le_default_level(&new_lev); - level_save(&new_lev,subset_name,1); -} - -void le_update_buttons(char *theme) -{ - int i; - char filename[1024]; - char pathname[1024]; - SDLKey key; - string_list_type bkgd_files; - string_list_type fgd_files; - - sprintf(pathname,"images/themes/%s",theme); - bkgd_files = dfiles(pathname,"bkgd-", NULL); - string_list_sort(&bkgd_files); - - le_bkgd_panel.hidden = YES; - key = SDLK_a; - for(i = 0; i < bkgd_files.num_items; ++i) - { - sprintf(filename,"%s/%s",pathname,bkgd_files.item[i]); - button_change_icon(&le_bkgd_panel.item[i],filename); - } - - sprintf(pathname,"images/themes/%s",theme); - fgd_files = dfiles(pathname,"solid", NULL); - string_list_sort(&fgd_files); - key = SDLK_a; - for(i = 0; i < fgd_files.num_items; ++i) - { - sprintf(filename,"%s/%s",pathname,fgd_files.item[i]); - button_change_icon(&le_fgd_panel.item[i],filename); - } - - string_list_free(&fgd_files); - fgd_files = dfiles(pathname,"brick", NULL); - string_list_sort(&fgd_files); - - for(i = 0; i < fgd_files.num_items; ++i) - { - sprintf(filename,"%s/%s",pathname,fgd_files.item[i]); - button_change_icon(&le_fgd_panel.item[i+14],filename); - } -} - -int le_init() -{ - int i,j; - char str[80]; - char filename[1024]; - SDLKey key; - string_list_type fgd_files; - string_list_type bkgd_files; - string_list_type bad_files; - level_subsets = dsubdirs("/levels", "info"); - - le_show_grid = YES; - - /* level_changed = NO;*/ - fire = DOWN; - done = 0; - le_frame = 0; /* support for frames in some tiles, like waves and bad guys */ - le_level_changed = NO; - - subset_init(&le_level_subset); - - le_current_level = NULL; - - le_current_tile = '.'; - le_mouse_pressed[LEFT] = NO; - le_mouse_pressed[RIGHT] = NO; - - texture_load(&le_selection,DATA_PREFIX "/images/leveleditor/select.png", USE_ALPHA); - - /* Load buttons */ - button_load(&le_save_level_bt,"/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32); - button_load(&le_next_level_bt,"/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0); - button_load(&le_previous_level_bt,"/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0); - button_load(&le_rubber_bt,"/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48); - button_load(&le_select_mode_one_bt,"/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48); - button_load(&le_select_mode_two_bt,"/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64); - button_load(&le_test_level_bt,"/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64); - button_load(&le_settings_bt,"/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64); - button_load(&le_move_left_bt,"/images/icons/left.png","Move left",SDLK_LEFT,0,0); - button_load(&le_move_right_bt,"/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0); - button_load(&le_fgd_bt,"/images/icons/fgd.png","Foreground tiles", SDLK_F7,screen->w-64,82); - button_load(&le_bkgd_bt,"/images/icons/bgd.png","Background tiles", SDLK_F8,screen->w-43,82); - button_load(&le_bad_bt,"/images/icons/emy.png","Enemies", SDLK_F9,screen->w-22,82); - - bkgd_files = dfiles("images/themes/antarctica","bkgd-", NULL); - string_list_sort(&bkgd_files); - - button_panel_init(&le_bkgd_panel, screen->w - 64,98, 64, 318); - le_bkgd_panel.hidden = YES; - key = SDLK_a; - for(i = 0; i < bkgd_files.num_items; ++i) - { - sprintf(filename,"images/themes/antarctica/%s",bkgd_files.item[i]); - button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i),0,0),i); - } - - string_list_free(&bkgd_files); - bkgd_files = dfiles("images/shared","cloud-", NULL); - string_list_sort(&bkgd_files); - - for(i = 0; i < bkgd_files.num_items; ++i) - { - sprintf(filename,"images/shared/%s",bkgd_files.item[i]); - button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i+8),0,0),i+8); - } - - fgd_files = dfiles("images/themes/antarctica","solid", NULL); - string_list_sort(&fgd_files); - key = SDLK_a; - button_panel_init(&le_fgd_panel, screen->w - 64,98, 64, 318); - for(i = 0; i < fgd_files.num_items; ++i) - { - sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]); - button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i),0,0),i); - } - - string_list_free(&fgd_files); - string_list_add_item(&fgd_files,"waves-0.png"); - string_list_add_item(&fgd_files,"water.png"); - string_list_add_item(&fgd_files,"pole.png"); - string_list_add_item(&fgd_files,"poletop.png"); - string_list_add_item(&fgd_files,"flag-0.png"); - string_list_add_item(&fgd_files,"box-empty.png"); - string_list_add_item(&fgd_files,"mints.png"); - string_list_add_item(&fgd_files,"distro-0.png"); - string_list_add_item(&fgd_files,"golden-herring.png"); - string_list_add_item(&fgd_files,"distro-0.png"); - - for(i = 0; i < fgd_files.num_items; ++i) - { - sprintf(filename,"images/shared/%s",fgd_files.item[i]); - button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+4),0,0),i+4); - } - - string_list_free(&fgd_files); - fgd_files = dfiles("images/themes/antarctica","brick", NULL); - string_list_sort(&fgd_files); - - for(i = 0; i < fgd_files.num_items; ++i) - { - sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]); - button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+14),0,0),i+14); - } - - string_list_free(&fgd_files); - string_list_add_item(&fgd_files,"distro-0.png"); - string_list_add_item(&fgd_files,"distro-0.png"); - for(i = 0; i < fgd_files.num_items; ++i) - { - sprintf(filename,"images/shared/%s",fgd_files.item[i]); - button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+16),0,0),i+16); - } - - le_fgd_panel.item[10].bkgd = &le_fgd_panel.item[9].icon; - le_fgd_panel.item[11].bkgd = &le_fgd_panel.item[9].icon; - le_fgd_panel.item[12].bkgd = &le_fgd_panel.item[9].icon; - le_fgd_panel.item[16].bkgd = &le_fgd_panel.item[14].icon; - le_fgd_panel.item[17].bkgd = &le_fgd_panel.item[15].icon; - - bad_files; - string_list_init(&bad_files); - string_list_add_item(&bad_files,"bsod-left-0.png"); - string_list_add_item(&bad_files,"laptop-left-0.png"); - string_list_add_item(&bad_files,"bag-left-0.png"); - button_panel_init(&le_bad_panel, screen->w - 64,98, 64, 318); - le_bad_panel.hidden = YES; - key = SDLK_a; - for(i = 0; i < bad_files.num_items; ++i) - { - sprintf(filename,"images/shared/%s",bad_files.item[i]); - button_panel_additem(&le_bad_panel,button_create(filename, "Bad Guy",(SDLKey)((int)key+i),0,0),i); - } - - menu_init(&leveleditor_menu); - menu_additem(&leveleditor_menu,menu_item_create(MN_LABEL,"Level Editor Menu",0,0)); - menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Return To Level Editor",0,0)); - menu_additem(&leveleditor_menu,menu_item_create(MN_DEACTIVE,"Level Subset Settings",0,&subset_settings_menu)); - menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"Load Level Subset",0,&subset_load_menu)); - menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"New Level Subset",0,&subset_new_menu)); - menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Quit Level Editor",0,0)); - - menu_reset(); - menu_set_current(&leveleditor_menu); - show_menu = YES; - - menu_init(&subset_load_menu); - menu_additem(&subset_load_menu,menu_item_create(MN_LABEL,"Load Level Subset",0,0)); - menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0)); - for(i = 0; i < level_subsets.num_items; ++i) - { - menu_additem(&subset_load_menu,menu_item_create(MN_ACTION,level_subsets.item[i],0,0)); - } - menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&subset_load_menu,menu_item_create(MN_BACK,"Back",0,0)); - - menu_init(&subset_new_menu); - menu_additem(&subset_new_menu,menu_item_create(MN_LABEL,"New Level Subset",0,0)); - menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&subset_new_menu,menu_item_create(MN_TEXTFIELD,"Enter Name",0,0)); - menu_additem(&subset_new_menu,menu_item_create(MN_ACTION,"Create",0,0)); - menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&subset_new_menu,menu_item_create(MN_BACK,"Back",0,0)); - - menu_init(&subset_settings_menu); - menu_additem(&subset_settings_menu,menu_item_create(MN_LABEL,"Level Subset Settings",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Title",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Description",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_ACTION,"Save Changes",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&subset_settings_menu,menu_item_create(MN_BACK,"Back",0,0)); - - menu_init(&level_settings_menu); - level_settings_menu.arrange_left = YES; - menu_additem(&level_settings_menu,menu_item_create(MN_LABEL,"Level Settings",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_TEXTFIELD,"Name ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Theme ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Song ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Bg-Image",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Length ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Time ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Gravity",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Red ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Green ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Blue ",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&level_settings_menu,menu_item_create(MN_ACTION,"Apply Changes",0,0)); - - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - - return 0; -} - -void update_level_settings_menu() -{ - char str[80]; - int i; - - menu_item_change_input(&level_settings_menu.item[2], le_current_level->name); - sprintf(str,"%d",le_current_level->width); - - string_list_copy(level_settings_menu.item[3].list, dsubdirs("images/themes", "solid0.png")); - string_list_copy(level_settings_menu.item[4].list, dfiles("music/",NULL, "-fast")); - string_list_copy(level_settings_menu.item[5].list, dfiles("images/background",NULL, NULL)); - string_list_add_item(level_settings_menu.item[5].list,""); - if((i = string_list_find(level_settings_menu.item[3].list,le_current_level->theme)) != -1) - level_settings_menu.item[3].list->active_item = i; - if((i = string_list_find(level_settings_menu.item[4].list,le_current_level->song_title)) != -1) - level_settings_menu.item[4].list->active_item = i; - if((i = string_list_find(level_settings_menu.item[5].list,le_current_level->bkgd_image)) != -1) - level_settings_menu.item[5].list->active_item = i; - - menu_item_change_input(&level_settings_menu.item[6], str); - sprintf(str,"%d",le_current_level->time_left); - menu_item_change_input(&level_settings_menu.item[7], str); - sprintf(str,"%2.0f",le_current_level->gravity); - menu_item_change_input(&level_settings_menu.item[8], str); - sprintf(str,"%d",le_current_level->bkgd_red); - menu_item_change_input(&level_settings_menu.item[9], str); - sprintf(str,"%d",le_current_level->bkgd_green); - menu_item_change_input(&level_settings_menu.item[10], str); - sprintf(str,"%d",le_current_level->bkgd_blue); - menu_item_change_input(&level_settings_menu.item[11], str); -} - -void update_subset_settings_menu() -{ - menu_item_change_input(&subset_settings_menu.item[2], le_level_subset.title); - menu_item_change_input(&subset_settings_menu.item[3], le_level_subset.description); -} - -void apply_level_settings_menu() -{ - int i,y,j; - i = NO; - - strcpy(le_current_level->name,level_settings_menu.item[2].input); - - if(strcmp(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list)) != 0) - { - strcpy(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list)); - i = YES; - } - - if(strcmp(le_current_level->theme,string_list_active(level_settings_menu.item[3].list)) != 0) - { - strcpy(le_current_level->theme,string_list_active(level_settings_menu.item[3].list)); - le_update_buttons(le_current_level->theme); - i = YES; - } - - if(i == YES) - { - level_free_gfx(); - level_load_gfx(le_current_level); - } - - strcpy(le_current_level->song_title,string_list_active(level_settings_menu.item[4].list)); - - i = le_current_level->width; - le_current_level->width = atoi(level_settings_menu.item[6].input); - if(le_current_level->width < i) - { - if(le_current_level->width < 21) - le_current_level->width = 21; - for(y = 0; y < 15; ++y) - { - le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char)); - le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0'; - } - } - else if(le_current_level->width > i) - { - for(y = 0; y < 15; ++y) - { - le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char)); - for(j = 0; j < le_current_level->width - i; ++j) - le_current_level->tiles[y][i+j] = (unsigned char) '.'; - le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0'; - } - } - le_current_level->time_left = atoi(level_settings_menu.item[7].input); - le_current_level->gravity = atof(level_settings_menu.item[8].input); - le_current_level->bkgd_red = atoi(level_settings_menu.item[9].input); - le_current_level->bkgd_green = atoi(level_settings_menu.item[10].input); - le_current_level->bkgd_blue = atoi(level_settings_menu.item[11].input); -} - -void save_subset_settings_menu() -{ - free(le_level_subset.title); - le_level_subset.title = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[2].input)+1)); - strcpy(le_level_subset.title,subset_settings_menu.item[2].input); - free(le_level_subset.description); - le_level_subset.description = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[3].input)+1)); - strcpy(le_level_subset.description,subset_settings_menu.item[3].input); - subset_save(&le_level_subset); -} - -void le_goto_level(int levelnb) -{ - arrays_free(); - arrays_init(); - - level_free(le_current_level); - if(level_load(le_current_level, le_level_subset.name, levelnb) != 0) - { - level_load(le_current_level, le_level_subset.name, le_level); - } - else - { - le_level = levelnb; - } - - le_set_defaults(); - - le_update_buttons(le_current_level->theme); - - level_free_gfx(); - level_load_gfx(le_current_level); - - le_activate_bad_guys(); -} - -void le_quit(void) -{ - /*if(level_changed == YES) - if(askforsaving() == CANCEL) - return;*/ //FIXME - - SDL_EnableKeyRepeat(0, 0); // disables key repeating - - texture_free(&le_selection); - menu_free(&leveleditor_menu); - menu_free(&subset_load_menu); - menu_free(&subset_new_menu); - menu_free(&subset_settings_menu); - menu_free(&level_settings_menu); - button_panel_free(&le_bkgd_panel); - button_panel_free(&le_fgd_panel); - button_panel_free(&le_bad_panel); - button_free(&le_save_level_bt); - button_free(&le_test_level_bt); - button_free(&le_next_level_bt); - button_free(&le_previous_level_bt); - button_free(&le_move_right_bt); - button_free(&le_move_left_bt); - button_free(&le_rubber_bt); - button_free(&le_select_mode_one_bt); - button_free(&le_select_mode_two_bt); - button_free(&le_settings_bt); - button_free(&le_bad_bt); - button_free(&le_bkgd_bt); - button_free(&le_fgd_bt); - - if(le_current_level != NULL) - { - level_free_gfx(); - level_free(le_current_level); - unloadshared(); - arrays_free(); - } -} - -void le_drawinterface() -{ - int x,y; - char str[80]; - - if(le_current_level != NULL) - { - /* draw a grid (if selected) */ - if(le_show_grid) - { - for(x = 0; x < 19; x++) - fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255); - for(y = 0; y < 15; y++) - fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255); - } - } - - if(le_selection_mode == CURSOR) - texture_draw(&le_selection, cursor_x - pos_x, cursor_y, NO_UPDATE); - else if(le_selection_mode == SQUARE) - { - int w, h; - le_highlight_selection(); - /* draw current selection */ - w = selection.x2 - selection.x1; - h = selection.y2 - selection.y1; - fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR); - fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR); - fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR); - fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR); - } - - - /* draw button bar */ - fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255); - drawshape(19 * 32, 14 * 32, le_current_tile); - switch(le_current_tile) - { - case 'B': - texture_draw(&img_mints, 19 * 32, 14 * 32, NO_UPDATE); - break; - case '!': - texture_draw(&img_golden_herring,19 * 32, 14 * 32, NO_UPDATE); - break; - case 'x': - case 'y': - case 'A': - texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32, NO_UPDATE); - break; - case '0': - texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32, NO_UPDATE); - break; - case '1': - texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32, NO_UPDATE); - break; - case '2': - texture_draw(&img_money_left[0],19 * 32, 14 * 32, NO_UPDATE); - break; - default: - break; - } - - if(le_current_level != NULL) - { - button_draw(&le_save_level_bt); - button_draw(&le_test_level_bt); - button_draw(&le_next_level_bt); - button_draw(&le_previous_level_bt); - button_draw(&le_rubber_bt); - button_draw(&le_select_mode_one_bt); - button_draw(&le_select_mode_two_bt); - button_draw(&le_settings_bt); - button_draw(&le_move_right_bt); - button_draw(&le_move_left_bt); - button_draw(&le_bad_bt); - button_draw(&le_bkgd_bt); - button_draw(&le_fgd_bt); - button_panel_draw(&le_bkgd_panel); - button_panel_draw(&le_fgd_panel); - button_panel_draw(&le_bad_panel); - - sprintf(str, "%d/%d", le_level,le_level_subset.levels); - text_drawf(&white_text, str, -8, 16, A_RIGHT, A_NONE, 1, NO_UPDATE); - - text_draw(&white_small_text, "F1 for Help", 10, 430, 1, NO_UPDATE); - } - else - { - if(show_menu == NO) - text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1, NO_UPDATE); - else - text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1, NO_UPDATE); - } - -} - -void le_drawlevel() -{ - int y,x,i,s; - static char str[LEVEL_NAME_MAX]; - - /* Draw the real background */ - if(le_current_level->bkgd_image[0] != '\0') - { - s = pos_x / 30; - texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h, NO_UPDATE); - texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h, NO_UPDATE); - } - else - { - clearscreen(le_current_level->bkgd_red, le_current_level->bkgd_green, le_current_level->bkgd_blue); - } - - /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */ - - for (y = 0; y < 15; ++y) - for (x = 0; x < 20; ++x) - { - drawshape(x * 32 - ((int)pos_x % 32), y * 32, le_current_level->tiles[y][x + (int)(pos_x / 32)]); - - /* draw whats inside stuff when cursor is selecting those */ - /* (draw them all the time - is this the right behaviour?) */ - switch(le_current_level->tiles[y][x + (int)(pos_x/32)]) - { - case 'B': - texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE); - break; - case '!': - texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE); - break; - case 'x': - case 'y': - case 'A': - texture_draw(&img_distro[(frame / 5) % 4], x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE); - break; - default: - break; - } - } - - /* Draw the Bad guys: */ - for (i = 0; i < num_bad_guys; ++i) - { - if(bad_guys[i].base.alive == NO) - continue; - /* to support frames: img_bsod_left[(frame / 5) % 4] */ - if(bad_guys[i].kind == BAD_BSOD) - texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE); - else if(bad_guys[i].kind == BAD_LAPTOP) - texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE); - else if (bad_guys[i].kind == BAD_MONEY) - texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE); - } - - - /* Draw the player: */ - /* for now, the position is fixed at (0, 240) */ - texture_draw(&tux_right[(frame / 5) % 3], 0 - pos_x, 240, NO_UPDATE); -} - -void le_checkevents() -{ - SDLKey key; - SDLMod keymod; - button_type* pbutton; - int x,y; - - keymod = SDL_GetModState(); - - while(SDL_PollEvent(&event)) - { - /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/ - if(event.type == SDL_KEYDOWN || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > 0 && event.motion.x < screen->w - 64 && - event.motion.y > 0 && event.motion.y < screen->h))) - { - - switch(event.type) - { - case SDL_KEYDOWN: // key pressed - key = event.key.keysym.sym; - if(show_menu) - { - menu_event(&event.key.keysym); - if(key == SDLK_ESCAPE) - { - show_menu = NO; - menu_set_current(&leveleditor_menu); - } - break; - } - switch(key) - { - case SDLK_ESCAPE: - if(!show_menu) - show_menu = YES; - else - show_menu = NO; - break; - case SDLK_LEFT: - if(fire == DOWN) - cursor_x -= KEY_CURSOR_SPEED; - else - cursor_x -= KEY_CURSOR_FASTSPEED; - - if(cursor_x < pos_x + MOUSE_LEFT_MARGIN) - pos_x = cursor_x - MOUSE_LEFT_MARGIN; - - break; - case SDLK_RIGHT: - if(fire == DOWN) - cursor_x += KEY_CURSOR_SPEED; - else - cursor_x += KEY_CURSOR_FASTSPEED; - - if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32) - pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32; - - break; - case SDLK_UP: - if(fire == DOWN) - cursor_y -= KEY_CURSOR_SPEED; - else - cursor_y -= KEY_CURSOR_FASTSPEED; - - if(cursor_y < 0) - cursor_y = 0; - break; - case SDLK_DOWN: - if(fire == DOWN) - cursor_y += KEY_CURSOR_SPEED; - else - cursor_y += KEY_CURSOR_FASTSPEED; - - if(cursor_y > screen->h-32) - cursor_y = screen->h-32; - break; - case SDLK_LCTRL: - fire =UP; - break; - case SDLK_F1: - le_showhelp(); - break; - case SDLK_HOME: - cursor_x = 0; - pos_x = cursor_x; - break; - case SDLK_END: - cursor_x = (le_current_level->width * 32) - 32; - pos_x = cursor_x; - break; - case SDLK_F9: - le_show_grid = !le_show_grid; - break; - default: - break; - } - break; - case SDL_KEYUP: /* key released */ - switch(event.key.keysym.sym) - { - case SDLK_LCTRL: - fire = DOWN; - break; - default: - break; - } - break; - case SDL_MOUSEBUTTONDOWN: - if(event.button.button == SDL_BUTTON_LEFT) - { - le_mouse_pressed[LEFT] = YES; - - selection.x1 = event.motion.x + pos_x; - selection.y1 = event.motion.y; - selection.x2 = event.motion.x + pos_x; - selection.y2 = event.motion.y; - } - else if(event.button.button == SDL_BUTTON_RIGHT) - le_mouse_pressed[RIGHT] = YES; - break; - case SDL_MOUSEBUTTONUP: - if(event.button.button == SDL_BUTTON_LEFT) - le_mouse_pressed[LEFT] = NO; - else if(event.button.button == SDL_BUTTON_RIGHT) - le_mouse_pressed[RIGHT] = NO; - break; - case SDL_MOUSEMOTION: - if(!show_menu) - { - x = event.motion.x; - y = event.motion.y; - - cursor_x = ((int)(pos_x + x) / 32) * 32; - cursor_y = ((int) y / 32) * 32; - - if(le_mouse_pressed[LEFT] == YES) - { - selection.x2 = x + pos_x; - selection.y2 = y; - } - - if(le_mouse_pressed[RIGHT] == YES) - { - pos_x += -1 * event.motion.xrel; - } - } - break; - case SDL_QUIT: // window closed - done = DONE_QUIT; - break; - default: - break; - } - } - - if(le_current_level != NULL) - { - if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > screen->w-64 && event.motion.x < screen->w && - event.motion.y > 0 && event.motion.y < screen->h))) - { - le_mouse_pressed[LEFT] = NO; - le_mouse_pressed[RIGHT] = NO; - - if(show_menu == NO) - { - /* Check for button events */ - button_event(&le_test_level_bt,&event); - if(button_get_state(&le_test_level_bt) == BN_CLICKED) - le_testlevel(); - button_event(&le_save_level_bt,&event); - if(button_get_state(&le_save_level_bt) == BN_CLICKED) - level_save(le_current_level,le_level_subset.name,le_level); - button_event(&le_next_level_bt,&event); - if(button_get_state(&le_next_level_bt) == BN_CLICKED) - { - if(le_level < le_level_subset.levels) - { - le_goto_level(++le_level); - } - else - { - st_level new_lev; - char str[1024]; - int d = 0; - sprintf(str,"Level %d doesn't exist.",le_level+1); - text_drawf(&white_text,str,0,-18,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE); - text_drawf(&white_text,"Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE); - text_drawf(&red_text,"(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE); - flipscreen(); - while(d == 0) - { - while(SDL_PollEvent(&event)) - switch(event.type) - { - case SDL_KEYDOWN: // key pressed - switch(event.key.keysym.sym) - { - case SDLK_y: - le_default_level(&new_lev); - level_save(&new_lev,le_level_subset.name,++le_level); - le_level_subset.levels = le_level; - le_goto_level(le_level); - d = 1; - break; - case SDLK_n: - d = 1; - break; - } - break; - default: - break; - } - SDL_Delay(50); - } - } - } - button_event(&le_previous_level_bt,&event); - if(button_get_state(&le_previous_level_bt) == BN_CLICKED) - { - if(le_level > 1) - le_goto_level(--le_level); - } - button_event(&le_rubber_bt,&event); - if(button_get_state(&le_rubber_bt) == BN_CLICKED) - le_current_tile = '.'; - button_event(&le_select_mode_one_bt,&event); - if(button_get_state(&le_select_mode_one_bt) == BN_CLICKED) - le_selection_mode = CURSOR; - button_event(&le_select_mode_two_bt,&event); - if(button_get_state(&le_select_mode_two_bt) == BN_CLICKED) - le_selection_mode = SQUARE; - - button_event(&le_bad_bt,&event); - if(button_get_state(&le_bad_bt) == BN_CLICKED) - { - le_bad_panel.hidden = NO; - le_fgd_panel.hidden = YES; - le_bkgd_panel.hidden = YES; - } - - button_event(&le_fgd_bt,&event); - if(button_get_state(&le_fgd_bt) == BN_CLICKED) - { - le_bad_panel.hidden = YES; - le_fgd_panel.hidden = NO; - le_bkgd_panel.hidden = YES; - } - button_event(&le_bkgd_bt,&event); - if(button_get_state(&le_bkgd_bt) == BN_CLICKED) - { - le_bad_panel.hidden = YES; - le_fgd_panel.hidden = YES; - le_bkgd_panel.hidden = NO; - } - button_event(&le_settings_bt,&event); - if(button_get_state(&le_settings_bt) == BN_CLICKED) - { - if(show_menu == NO) - { - update_level_settings_menu(); - menu_set_current(&level_settings_menu); - show_menu = YES; - } - else - { - menu_set_current(&leveleditor_menu); - show_menu = NO; - } - } - if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL) - { - if(button_get_state(pbutton) == BN_CLICKED) - { - char c = '\0'; - if(pbutton->tag >= 0 && pbutton->tag <= 3) - c = 'G' + pbutton->tag; - else if(pbutton->tag >= 4 && pbutton->tag <= 7) - c = 'g' + pbutton->tag - 4; - else if(pbutton->tag >= 8 && pbutton->tag <= 11) - c = 'C' + pbutton->tag - 8; - else if(pbutton->tag >= 12 && pbutton->tag <= 15) - c = 'c' + pbutton->tag - 12; - if(c != '\0') - le_current_tile = c; - } - } - if((pbutton = button_panel_event(&le_fgd_panel,&event)) != NULL) - { - if(button_get_state(pbutton) == BN_CLICKED) - { - char c = '\0'; - if(pbutton->tag == 0) - c = '#' ; - else if(pbutton->tag == 1) - c = '['; - else if(pbutton->tag == 2) - c = '='; - else if(pbutton->tag == 3) - c = ']'; - else if(pbutton->tag == 4) - c = '^'; - else if(pbutton->tag == 5) - c = '&'; - else if(pbutton->tag == 6) - c = '|'; - else if(pbutton->tag == 7) - c = '*'; - else if(pbutton->tag == 8) - c = '\\'; - else if(pbutton->tag == 9) - c = 'a'; - else if(pbutton->tag == 10) - c = 'B'; - else if(pbutton->tag == 11) - c = 'A'; - else if(pbutton->tag == 12) - c = '!'; - else if(pbutton->tag == 13) - c = '$'; - else if(pbutton->tag == 14) - c = 'X'; - else if(pbutton->tag == 15) - c = 'Y'; - else if(pbutton->tag == 16) - c = 'x'; - else if(pbutton->tag == 17) - c = 'y'; - if(c != '\0') - le_current_tile = c; - } - } - if((pbutton = button_panel_event(&le_bad_panel,&event)) != NULL) - { - if(button_get_state(pbutton) == BN_CLICKED) - { - char c = '\0'; - if(pbutton->tag >= 0 && pbutton->tag <= 2) - c = '0' + pbutton->tag; - if(c != '\0') - le_current_tile = c; - } - } - } - else - { - button_event(&le_settings_bt,&event); - if(button_get_state(&le_settings_bt) == BN_CLICKED) - { - if(show_menu == NO) - { - update_level_settings_menu(); - menu_set_current(&level_settings_menu); - show_menu = YES; - } - else - { - menu_set_current(&leveleditor_menu); - show_menu = NO; - } - } - } - } - if(show_menu == NO) - { - button_event(&le_move_left_bt,&event); - button_event(&le_move_right_bt,&event); - - if(le_mouse_pressed[LEFT]) - { - le_change(cursor_x, cursor_y, le_current_tile); - } - } - } - } - if(show_menu == NO) - { - if(button_get_state(&le_move_left_bt) == BN_PRESSED) - { - pos_x -= 192; - } - else if(button_get_state(&le_move_left_bt) == BN_HOVER) - { - pos_x -= 96; - } - - if(button_get_state(&le_move_right_bt) == BN_PRESSED) - { - pos_x += 192; - } - else if(button_get_state(&le_move_right_bt) == BN_HOVER) - { - pos_x += 96; - } - } - -} - -void le_highlight_selection() -{ - int x,y,i; - int x1, x2, y1, y2; - - if(selection.x1 < selection.x2) - { - x1 = selection.x1; - x2 = selection.x2; - } - else - { - x1 = selection.x2; - x2 = selection.x1; - } - if(selection.y1 < selection.y2) - { - y1 = selection.y1; - y2 = selection.y2; - } - else - { - y1 = selection.y2; - y2 = selection.y1; - } - - x1 /= 32; - x2 /= 32; - y1 /= 32; - y2 /= 32; - - fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103); -} - -void le_change(float x, float y, unsigned char c) -{ - if(le_current_level != NULL) - { - int xx,yy,i; - int x1, x2, y1, y2; - - /* level_changed = YES; */ - - switch(le_selection_mode) - { - case CURSOR: - level_change(le_current_level,x,y,c); - - yy = ((int)y / 32); - xx = ((int)x / 32); - - /* if there is a bad guy over there, remove it */ - for(i = 0; i < num_bad_guys; ++i) - if (bad_guys[i].base.alive) - if(xx == bad_guys[i].base.x/32 && yy == bad_guys[i].base.y/32) - bad_guys[i].base.alive = NO; - - if(c == '0') /* if it's a bad guy */ - add_bad_guy(xx*32, yy*32, BAD_BSOD); - else if(c == '1') - add_bad_guy(xx*32, yy*32, BAD_LAPTOP); - else if(c == '2') - add_bad_guy(xx*32, yy*32, BAD_MONEY); - - break; - case SQUARE: - if(selection.x1 < selection.x2) - { - x1 = selection.x1; - x2 = selection.x2; - } - else - { - x1 = selection.x2; - x2 = selection.x1; - } - if(selection.y1 < selection.y2) - { - y1 = selection.y1; - y2 = selection.y2; - } - else - { - y1 = selection.y2; - y2 = selection.y1; - } - - x1 /= 32; - x2 /= 32; - y1 /= 32; - y2 /= 32; - - /* if there is a bad guy over there, remove it */ - for(i = 0; i < num_bad_guys; ++i) - if(bad_guys[i].base.alive) - if(bad_guys[i].base.x/32 >= x1 && bad_guys[i].base.x/32 <= x2 - && bad_guys[i].base.y/32 >= y1 && bad_guys[i].base.y/32 <= y2) - bad_guys[i].base.alive = NO; - - for(xx = x1; xx <= x2; xx++) - for(yy = y1; yy <= y2; yy++) - { - level_change(le_current_level, xx*32, yy*32, c); - - if(c == '0') // if it's a bad guy - add_bad_guy(xx*32, yy*32, BAD_BSOD); - else if(c == '1') - add_bad_guy(xx*32, yy*32, BAD_LAPTOP); - else if(c == '2') - add_bad_guy(xx*32, yy*32, BAD_MONEY); - } - break; - default: - break; - } - } -} - -void le_testlevel() -{ - level_save(le_current_level,"test",le_level); - gameloop("test",le_level, ST_GL_TEST); - menu_set_current(&leveleditor_menu); - arrays_init(); - level_load_gfx(le_current_level); - loadshared(); - le_activate_bad_guys(); -} - -void le_showhelp() -{ - SDL_Event event; - int i, done; - char *text[] = { - " - This is SuperTux's built-in level editor -", - "It has been designed to be light and easy to use from the start.", - "", - "When you first load the level editor you are given a menu where you", - "can load level subsets, create a new level subset, edit the current", - "subset's settings, or simply quit the editor. You can access this menu", - "from the level editor at any time by pressing the escape key.", - "", - "To your right is your button bar. The center of this contains many", - "tiles you can use to make your level. To select a tile, click on it", - "with your left mouse button; your selection will be shown in the", - "bottom right corner of the button box. Click anywhere on your level", - "with the left mouse button to place that tile down. If you right click", - "a tile in the button bar, you can find out what its keyboard shortcut", - "is. The three buttons FGD, BGD and EMY let you pick from foreground,", - "background, and enemy tiles. The eraser lets you remove tiles.", - "The left and right arrow keys scroll back and forth through your level.", - "The button with the wrench and screwdriver, lets you change the", - "settings of your level, including how long it is or what music it will", - "play. When you are ready to give your level a test, click on the little", - "running Tux. If you like the changes you have made to your level,", - "press the red save key to keep them.", - "To change which level in your subset you are editing, press the white", - "up and down arrow keys at the top of the button box.", - "", - "Have fun making levels! If you make some good ones, send them to us on", - "the SuperTux mailing list!", - "- SuperTux team" - }; - - - text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2, NO_UPDATE); - - for(i = 0; i < sizeof(text)/sizeof(char *); i++) - text_draw(&white_small_text, text[i], 5, 80+(i*12), 1, NO_UPDATE); - - text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - - flipscreen(); - - done = 0; - - while(done == 0) - { - while(SDL_PollEvent(&event)) - switch(event.type) - { - case SDL_MOUSEBUTTONDOWN: // mouse pressed - case SDL_KEYDOWN: // key pressed - done = 1; - break; - default: - break; - } - SDL_Delay(50); - } -} diff --git a/src/leveleditor.cpp b/src/leveleditor.cpp new file mode 100644 index 000000000..d0d7b9e13 --- /dev/null +++ b/src/leveleditor.cpp @@ -0,0 +1,1517 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +/* December 28, 2003 - March 15, 2004 */ + +/* leveleditor.c - A built-in level editor for SuperTux + Ricardo Cruz + Tobias Glaesser */ + +#include +#include +#include +#include +#include +#include +#include +#include "leveleditor.h" + +#include "screen.h" +#include "defines.h" +#include "globals.h" +#include "setup.h" +#include "menu.h" +#include "level.h" +#include "badguy.h" +#include "scene.h" +#include "button.h" + +/* definitions to aid development */ +#define DONE_LEVELEDITOR 1 +#define DONE_QUIT 2 +#define DONE_CHANGELEVEL 3 + +/* definitions that affect gameplay */ +#define KEY_CURSOR_SPEED 32 +#define KEY_CURSOR_FASTSPEED 64 + +/* when pagedown/up pressed speed:*/ +#define PAGE_CURSOR_SPEED 13*32 + +#define MOUSE_LEFT_MARGIN 80 +#define MOUSE_RIGHT_MARGIN (560-32) +/* right_margin should noticed that the cursor is 32 pixels, + so it should subtract that value */ +#define MOUSE_POS_SPEED 20 + +/* look */ +#define SELECT_W 2 // size of the selections lines +#define SELECT_CLR 0, 255, 0, 255 // lines color (R, G, B, A) + +/* gameloop funcs declerations */ + +void loadshared(void); +void unloadshared(void); + +/* own declerations */ +/* crutial ones (main loop) */ +int le_init(); +void le_quit(); +void le_drawlevel(); +void le_drawinterface(); +void le_checkevents(); +void le_change(float x, float y, unsigned char c); +void le_testlevel(); +void le_showhelp(); +void le_set_defaults(void); +void le_activate_bad_guys(void); +void le_new_subset(char *subset_name); + +void le_highlight_selection(); + +void apply_level_settings_menu(); +void update_subset_settings_menu(); +void save_subset_settings_menu(); +void le_update_buttons(char*); + +/* leveleditor internals */ +static string_list_type level_subsets; +static int le_level_changed; /* if changes, ask for saving, when quiting*/ +static int pos_x, cursor_x, cursor_y, cursor_tile, fire; +static int le_level; +static st_level* le_current_level; +static st_subset le_level_subset; +static int le_show_grid; +static int le_frame; +static texture_type le_selection; +static int done; +static char le_current_tile; +static int le_mouse_pressed[2]; +static button_type le_save_level_bt; +static button_type le_test_level_bt; +static button_type le_next_level_bt; +static button_type le_previous_level_bt; +static button_type le_move_right_bt; +static button_type le_move_left_bt; +static button_type le_rubber_bt; +static button_type le_select_mode_one_bt; +static button_type le_select_mode_two_bt; +static button_type le_settings_bt; +static button_type le_bad_bt; +static button_type le_bkgd_bt; +static button_type le_fgd_bt; +static button_panel_type le_bkgd_panel; +static button_panel_type le_fgd_panel; +static button_panel_type le_bad_panel; +static menu_type leveleditor_menu; +static menu_type subset_load_menu; +static menu_type subset_new_menu; +static menu_type subset_settings_menu; +static menu_type level_settings_menu; + +static square selection; +static int le_selection_mode; +static SDL_Event event; + +void le_activate_bad_guys(void) +{ + int x,y; + + /* Activate bad guys: */ + + /* as oposed to the gameloop.c func, this one doesn't remove + the badguys from tiles */ + + for (y = 0; y < 15; ++y) + for (x = 0; x < le_current_level->width; ++x) + if (le_current_level->tiles[y][x] >= '0' && le_current_level->tiles[y][x] <= '9') + add_bad_guy(x * 32, y * 32, le_current_level->tiles[y][x] - '0'); +} + +void le_set_defaults() +{ + if(le_current_level != NULL) + { + /* Set defaults: */ + + if(le_current_level->time_left == 0) + le_current_level->time_left = 255; + } +} + +int leveleditor(int levelnb) +{ + int last_time, now_time, i; + + le_level = levelnb; + if(le_init() != 0) + return 1; + + /* Clear screen: */ + + clearscreen(0, 0, 0); + updatescreen(); + + while (SDL_PollEvent(&event)) + {} + + while(YES) + { + last_time = SDL_GetTicks(); + le_frame++; + + le_checkevents(); + + if(le_current_level != NULL) + { + /* making events results to be in order */ + if(pos_x < 0) + pos_x = 0; + if(pos_x > (le_current_level->width * 32) - screen->w) + pos_x = (le_current_level->width * 32) - screen->w; + + /* draw the level */ + le_drawlevel(); + } + else + clearscreen(0, 0, 0); + + /* draw editor interface */ + le_drawinterface(); + + if(show_menu) + { + menu_process_current(); + if(current_menu == &leveleditor_menu) + { + switch (menu_check(&leveleditor_menu)) + { + case 2: + show_menu = NO; + break; + case 3: + update_subset_settings_menu(); + break; + case 7: + done = DONE_LEVELEDITOR; + break; + } + } + else if(current_menu == &level_settings_menu) + { + switch (menu_check(&level_settings_menu)) + { + case 13: + apply_level_settings_menu(); + menu_set_current(&leveleditor_menu); + break; + default: + show_menu = YES; + break; + } + } + else if(current_menu == &subset_load_menu) + { + switch (i = menu_check(&subset_load_menu)) + { + case 0: + break; + default: + if(i != -1) + { + subset_load(&le_level_subset,level_subsets.item[i-2]); + leveleditor_menu.item[3].kind = MN_GOTO; + le_level = 1; + arrays_init(); + loadshared(); + le_current_level = (st_level*) malloc(sizeof(st_level)); + if(level_load(le_current_level, le_level_subset.name, le_level) != 0) + { + le_quit(); + return 1; + } + le_update_buttons(le_current_level->theme); + le_set_defaults(); + level_load_gfx(le_current_level); + le_activate_bad_guys(); + show_menu = YES; + } + break; + } + } + else if(current_menu == &subset_new_menu) + { + if(subset_new_menu.item[2].input[0] == '\0') + subset_new_menu.item[3].kind = MN_DEACTIVE; + else + { + subset_new_menu.item[3].kind = MN_ACTION; + + switch (i = menu_check(&subset_new_menu)) + { + case 3: + le_new_subset(subset_new_menu.item[2].input); + subset_load(&le_level_subset,subset_new_menu.item[2].input); + leveleditor_menu.item[3].kind = MN_GOTO; + le_level = 1; + arrays_init(); + loadshared(); + le_current_level = (st_level*) malloc(sizeof(st_level)); + if(level_load(le_current_level, le_level_subset.name, le_level) != 0) + { + le_quit(); + return 1; + } + le_update_buttons(le_current_level->theme); + le_set_defaults(); + level_load_gfx(le_current_level); + le_activate_bad_guys(); + menu_item_change_input(&subset_new_menu.item[2],""); + show_menu = YES; + break; + } + } + } + else if(current_menu == &subset_settings_menu) + { + if(strcmp(le_level_subset.title,subset_settings_menu.item[2].input) == 0 && strcmp(le_level_subset.description,subset_settings_menu.item[3].input) == 0 ) + subset_settings_menu.item[5].kind = MN_DEACTIVE; + else + subset_settings_menu.item[5].kind = MN_ACTION; + + switch (i = menu_check(&subset_settings_menu)) + { + case 5: + save_subset_settings_menu(); + show_menu = YES; + break; + } + } + } + + if(done) + { + le_quit(); + return 0; + } + + if(done == DONE_QUIT) + { + le_quit(); + return 1; + } + + SDL_Delay(25); + now_time = SDL_GetTicks(); + if (now_time < last_time + FPS) + SDL_Delay(last_time + FPS - now_time); /* delay some time */ + + flipscreen(); + } + + return done; +} + +void le_default_level(st_level* plevel) +{ + int i,y; + strcpy(plevel->name,"UnNamed"); + strcpy(plevel->theme,"antarctica"); + strcpy(plevel->song_title,"Mortimers_chipdisko.mod"); + strcpy(plevel->bkgd_image,"arctis.png"); + plevel->width = 21; + plevel->time_left = 100; + plevel->gravity = 10.; + plevel->bkgd_red = 0; + plevel->bkgd_green = 0; + plevel->bkgd_blue = 0; + + for(i = 0; i < 15; ++i) + { + plevel->tiles[i] = (unsigned char*) malloc((plevel->width+1)*sizeof(unsigned char)); + plevel->tiles[i][plevel->width] = (unsigned char) '\0'; + for(y = 0; y < plevel->width; ++y) + plevel->tiles[i][y] = (unsigned char) '.'; + plevel->tiles[i][plevel->width] = (unsigned char) '\0'; + } +} + +void le_new_subset(char *subset_name) +{ + st_level new_lev; + st_subset new_subset; + new_subset.name = (char*) malloc((strlen(subset_name)+1)*sizeof(char)); + strcpy(new_subset.name,subset_name); + new_subset.title = (char*) malloc((strlen("Unknown Title")+1)*sizeof(char)); + strcpy(new_subset.title,"Unknown Title"); + new_subset.description = (char*) malloc((strlen("No description so far.")+1)*sizeof(char)); + strcpy(new_subset.description,"No description so far."); + subset_save(&new_subset); + le_default_level(&new_lev); + level_save(&new_lev,subset_name,1); +} + +void le_update_buttons(char *theme) +{ + int i; + char filename[1024]; + char pathname[1024]; + SDLKey key; + string_list_type bkgd_files; + string_list_type fgd_files; + + sprintf(pathname,"images/themes/%s",theme); + bkgd_files = dfiles(pathname,"bkgd-", NULL); + string_list_sort(&bkgd_files); + + le_bkgd_panel.hidden = YES; + key = SDLK_a; + for(i = 0; i < bkgd_files.num_items; ++i) + { + sprintf(filename,"%s/%s",pathname,bkgd_files.item[i]); + button_change_icon(&le_bkgd_panel.item[i],filename); + } + + sprintf(pathname,"images/themes/%s",theme); + fgd_files = dfiles(pathname,"solid", NULL); + string_list_sort(&fgd_files); + key = SDLK_a; + for(i = 0; i < fgd_files.num_items; ++i) + { + sprintf(filename,"%s/%s",pathname,fgd_files.item[i]); + button_change_icon(&le_fgd_panel.item[i],filename); + } + + string_list_free(&fgd_files); + fgd_files = dfiles(pathname,"brick", NULL); + string_list_sort(&fgd_files); + + for(i = 0; i < fgd_files.num_items; ++i) + { + sprintf(filename,"%s/%s",pathname,fgd_files.item[i]); + button_change_icon(&le_fgd_panel.item[i+14],filename); + } +} + +int le_init() +{ + int i,j; + char str[80]; + char filename[1024]; + SDLKey key; + string_list_type fgd_files; + string_list_type bkgd_files; + string_list_type bad_files; + level_subsets = dsubdirs("/levels", "info"); + + le_show_grid = YES; + + /* level_changed = NO;*/ + fire = DOWN; + done = 0; + le_frame = 0; /* support for frames in some tiles, like waves and bad guys */ + le_level_changed = NO; + + subset_init(&le_level_subset); + + le_current_level = NULL; + + le_current_tile = '.'; + le_mouse_pressed[LEFT] = NO; + le_mouse_pressed[RIGHT] = NO; + + texture_load(&le_selection,DATA_PREFIX "/images/leveleditor/select.png", USE_ALPHA); + + /* Load buttons */ + button_load(&le_save_level_bt,"/images/icons/save.png","Save level", SDLK_F6,screen->w-64,32); + button_load(&le_next_level_bt,"/images/icons/up.png","Next level", SDLK_PAGEUP,screen->w-64,0); + button_load(&le_previous_level_bt,"/images/icons/down.png","Previous level",SDLK_PAGEDOWN,screen->w-32,0); + button_load(&le_rubber_bt,"/images/icons/rubber.png","Rubber",SDLK_DELETE,screen->w-32,48); + button_load(&le_select_mode_one_bt,"/images/icons/select-mode1.png","Select single tile",SDLK_F3,screen->w-64,48); + button_load(&le_select_mode_two_bt,"/images/icons/select-mode2.png","Select multiple tiles",SDLK_F3,screen->w-64,64); + button_load(&le_test_level_bt,"/images/icons/test-level.png","Test level",SDLK_F4,screen->w-64,screen->h - 64); + button_load(&le_settings_bt,"/images/icons/settings.png","Level settings",SDLK_F5,screen->w-32,screen->h - 64); + button_load(&le_move_left_bt,"/images/icons/left.png","Move left",SDLK_LEFT,0,0); + button_load(&le_move_right_bt,"/images/icons/right.png","Move right",SDLK_RIGHT,screen->w-80,0); + button_load(&le_fgd_bt,"/images/icons/fgd.png","Foreground tiles", SDLK_F7,screen->w-64,82); + button_load(&le_bkgd_bt,"/images/icons/bgd.png","Background tiles", SDLK_F8,screen->w-43,82); + button_load(&le_bad_bt,"/images/icons/emy.png","Enemies", SDLK_F9,screen->w-22,82); + + bkgd_files = dfiles("images/themes/antarctica","bkgd-", NULL); + string_list_sort(&bkgd_files); + + button_panel_init(&le_bkgd_panel, screen->w - 64,98, 64, 318); + le_bkgd_panel.hidden = YES; + key = SDLK_a; + for(i = 0; i < bkgd_files.num_items; ++i) + { + sprintf(filename,"images/themes/antarctica/%s",bkgd_files.item[i]); + button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i),0,0),i); + } + + string_list_free(&bkgd_files); + bkgd_files = dfiles("images/shared","cloud-", NULL); + string_list_sort(&bkgd_files); + + for(i = 0; i < bkgd_files.num_items; ++i) + { + sprintf(filename,"images/shared/%s",bkgd_files.item[i]); + button_panel_additem(&le_bkgd_panel,button_create(filename, "Background Tile",(SDLKey)((int)key+i+8),0,0),i+8); + } + + fgd_files = dfiles("images/themes/antarctica","solid", NULL); + string_list_sort(&fgd_files); + key = SDLK_a; + button_panel_init(&le_fgd_panel, screen->w - 64,98, 64, 318); + for(i = 0; i < fgd_files.num_items; ++i) + { + sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]); + button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i),0,0),i); + } + + string_list_free(&fgd_files); + string_list_add_item(&fgd_files,"waves-0.png"); + string_list_add_item(&fgd_files,"water.png"); + string_list_add_item(&fgd_files,"pole.png"); + string_list_add_item(&fgd_files,"poletop.png"); + string_list_add_item(&fgd_files,"flag-0.png"); + string_list_add_item(&fgd_files,"box-empty.png"); + string_list_add_item(&fgd_files,"mints.png"); + string_list_add_item(&fgd_files,"distro-0.png"); + string_list_add_item(&fgd_files,"golden-herring.png"); + string_list_add_item(&fgd_files,"distro-0.png"); + + for(i = 0; i < fgd_files.num_items; ++i) + { + sprintf(filename,"images/shared/%s",fgd_files.item[i]); + button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+4),0,0),i+4); + } + + string_list_free(&fgd_files); + fgd_files = dfiles("images/themes/antarctica","brick", NULL); + string_list_sort(&fgd_files); + + for(i = 0; i < fgd_files.num_items; ++i) + { + sprintf(filename,"images/themes/antarctica/%s",fgd_files.item[i]); + button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+14),0,0),i+14); + } + + string_list_free(&fgd_files); + string_list_add_item(&fgd_files,"distro-0.png"); + string_list_add_item(&fgd_files,"distro-0.png"); + for(i = 0; i < fgd_files.num_items; ++i) + { + sprintf(filename,"images/shared/%s",fgd_files.item[i]); + button_panel_additem(&le_fgd_panel,button_create(filename, "Foreground Tile",(SDLKey)((int)key+i+16),0,0),i+16); + } + + le_fgd_panel.item[10].bkgd = &le_fgd_panel.item[9].icon; + le_fgd_panel.item[11].bkgd = &le_fgd_panel.item[9].icon; + le_fgd_panel.item[12].bkgd = &le_fgd_panel.item[9].icon; + le_fgd_panel.item[16].bkgd = &le_fgd_panel.item[14].icon; + le_fgd_panel.item[17].bkgd = &le_fgd_panel.item[15].icon; + + bad_files; + string_list_init(&bad_files); + string_list_add_item(&bad_files,"bsod-left-0.png"); + string_list_add_item(&bad_files,"laptop-left-0.png"); + string_list_add_item(&bad_files,"bag-left-0.png"); + button_panel_init(&le_bad_panel, screen->w - 64,98, 64, 318); + le_bad_panel.hidden = YES; + key = SDLK_a; + for(i = 0; i < bad_files.num_items; ++i) + { + sprintf(filename,"images/shared/%s",bad_files.item[i]); + button_panel_additem(&le_bad_panel,button_create(filename, "Bad Guy",(SDLKey)((int)key+i),0,0),i); + } + + menu_init(&leveleditor_menu); + menu_additem(&leveleditor_menu,menu_item_create(MN_LABEL,"Level Editor Menu",0,0)); + menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Return To Level Editor",0,0)); + menu_additem(&leveleditor_menu,menu_item_create(MN_DEACTIVE,"Level Subset Settings",0,&subset_settings_menu)); + menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"Load Level Subset",0,&subset_load_menu)); + menu_additem(&leveleditor_menu,menu_item_create(MN_GOTO,"New Level Subset",0,&subset_new_menu)); + menu_additem(&leveleditor_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&leveleditor_menu,menu_item_create(MN_ACTION,"Quit Level Editor",0,0)); + + menu_reset(); + menu_set_current(&leveleditor_menu); + show_menu = YES; + + menu_init(&subset_load_menu); + menu_additem(&subset_load_menu,menu_item_create(MN_LABEL,"Load Level Subset",0,0)); + menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0)); + for(i = 0; i < level_subsets.num_items; ++i) + { + menu_additem(&subset_load_menu,menu_item_create(MN_ACTION,level_subsets.item[i],0,0)); + } + menu_additem(&subset_load_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&subset_load_menu,menu_item_create(MN_BACK,"Back",0,0)); + + menu_init(&subset_new_menu); + menu_additem(&subset_new_menu,menu_item_create(MN_LABEL,"New Level Subset",0,0)); + menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&subset_new_menu,menu_item_create(MN_TEXTFIELD,"Enter Name",0,0)); + menu_additem(&subset_new_menu,menu_item_create(MN_ACTION,"Create",0,0)); + menu_additem(&subset_new_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&subset_new_menu,menu_item_create(MN_BACK,"Back",0,0)); + + menu_init(&subset_settings_menu); + menu_additem(&subset_settings_menu,menu_item_create(MN_LABEL,"Level Subset Settings",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Title",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_TEXTFIELD,"Description",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_ACTION,"Save Changes",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&subset_settings_menu,menu_item_create(MN_BACK,"Back",0,0)); + + menu_init(&level_settings_menu); + level_settings_menu.arrange_left = YES; + menu_additem(&level_settings_menu,menu_item_create(MN_LABEL,"Level Settings",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_TEXTFIELD,"Name ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Theme ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Song ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_STRINGSELECT,"Bg-Image",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Length ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Time ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Gravity",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Red ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Green ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_NUMFIELD,"Blue ",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&level_settings_menu,menu_item_create(MN_ACTION,"Apply Changes",0,0)); + + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + return 0; +} + +void update_level_settings_menu() +{ + char str[80]; + int i; + + menu_item_change_input(&level_settings_menu.item[2], le_current_level->name); + sprintf(str,"%d",le_current_level->width); + + string_list_copy(level_settings_menu.item[3].list, dsubdirs("images/themes", "solid0.png")); + string_list_copy(level_settings_menu.item[4].list, dfiles("music/",NULL, "-fast")); + string_list_copy(level_settings_menu.item[5].list, dfiles("images/background",NULL, NULL)); + string_list_add_item(level_settings_menu.item[5].list,""); + if((i = string_list_find(level_settings_menu.item[3].list,le_current_level->theme)) != -1) + level_settings_menu.item[3].list->active_item = i; + if((i = string_list_find(level_settings_menu.item[4].list,le_current_level->song_title)) != -1) + level_settings_menu.item[4].list->active_item = i; + if((i = string_list_find(level_settings_menu.item[5].list,le_current_level->bkgd_image)) != -1) + level_settings_menu.item[5].list->active_item = i; + + menu_item_change_input(&level_settings_menu.item[6], str); + sprintf(str,"%d",le_current_level->time_left); + menu_item_change_input(&level_settings_menu.item[7], str); + sprintf(str,"%2.0f",le_current_level->gravity); + menu_item_change_input(&level_settings_menu.item[8], str); + sprintf(str,"%d",le_current_level->bkgd_red); + menu_item_change_input(&level_settings_menu.item[9], str); + sprintf(str,"%d",le_current_level->bkgd_green); + menu_item_change_input(&level_settings_menu.item[10], str); + sprintf(str,"%d",le_current_level->bkgd_blue); + menu_item_change_input(&level_settings_menu.item[11], str); +} + +void update_subset_settings_menu() +{ + menu_item_change_input(&subset_settings_menu.item[2], le_level_subset.title); + menu_item_change_input(&subset_settings_menu.item[3], le_level_subset.description); +} + +void apply_level_settings_menu() +{ + int i,y,j; + i = NO; + + strcpy(le_current_level->name,level_settings_menu.item[2].input); + + if(strcmp(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list)) != 0) + { + strcpy(le_current_level->bkgd_image,string_list_active(level_settings_menu.item[5].list)); + i = YES; + } + + if(strcmp(le_current_level->theme,string_list_active(level_settings_menu.item[3].list)) != 0) + { + strcpy(le_current_level->theme,string_list_active(level_settings_menu.item[3].list)); + le_update_buttons(le_current_level->theme); + i = YES; + } + + if(i == YES) + { + level_free_gfx(); + level_load_gfx(le_current_level); + } + + strcpy(le_current_level->song_title,string_list_active(level_settings_menu.item[4].list)); + + i = le_current_level->width; + le_current_level->width = atoi(level_settings_menu.item[6].input); + if(le_current_level->width < i) + { + if(le_current_level->width < 21) + le_current_level->width = 21; + for(y = 0; y < 15; ++y) + { + le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char)); + le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0'; + } + } + else if(le_current_level->width > i) + { + for(y = 0; y < 15; ++y) + { + le_current_level->tiles[y] = (unsigned char*) realloc(le_current_level->tiles[y],(le_current_level->width+1)*sizeof(unsigned char)); + for(j = 0; j < le_current_level->width - i; ++j) + le_current_level->tiles[y][i+j] = (unsigned char) '.'; + le_current_level->tiles[y][le_current_level->width] = (unsigned char) '\0'; + } + } + le_current_level->time_left = atoi(level_settings_menu.item[7].input); + le_current_level->gravity = atof(level_settings_menu.item[8].input); + le_current_level->bkgd_red = atoi(level_settings_menu.item[9].input); + le_current_level->bkgd_green = atoi(level_settings_menu.item[10].input); + le_current_level->bkgd_blue = atoi(level_settings_menu.item[11].input); +} + +void save_subset_settings_menu() +{ + free(le_level_subset.title); + le_level_subset.title = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[2].input)+1)); + strcpy(le_level_subset.title,subset_settings_menu.item[2].input); + free(le_level_subset.description); + le_level_subset.description = (char*) malloc(sizeof(char)*(strlen(subset_settings_menu.item[3].input)+1)); + strcpy(le_level_subset.description,subset_settings_menu.item[3].input); + subset_save(&le_level_subset); +} + +void le_goto_level(int levelnb) +{ + arrays_free(); + arrays_init(); + + level_free(le_current_level); + if(level_load(le_current_level, le_level_subset.name, levelnb) != 0) + { + level_load(le_current_level, le_level_subset.name, le_level); + } + else + { + le_level = levelnb; + } + + le_set_defaults(); + + le_update_buttons(le_current_level->theme); + + level_free_gfx(); + level_load_gfx(le_current_level); + + le_activate_bad_guys(); +} + +void le_quit(void) +{ + /*if(level_changed == YES) + if(askforsaving() == CANCEL) + return;*/ //FIXME + + SDL_EnableKeyRepeat(0, 0); // disables key repeating + + texture_free(&le_selection); + menu_free(&leveleditor_menu); + menu_free(&subset_load_menu); + menu_free(&subset_new_menu); + menu_free(&subset_settings_menu); + menu_free(&level_settings_menu); + button_panel_free(&le_bkgd_panel); + button_panel_free(&le_fgd_panel); + button_panel_free(&le_bad_panel); + button_free(&le_save_level_bt); + button_free(&le_test_level_bt); + button_free(&le_next_level_bt); + button_free(&le_previous_level_bt); + button_free(&le_move_right_bt); + button_free(&le_move_left_bt); + button_free(&le_rubber_bt); + button_free(&le_select_mode_one_bt); + button_free(&le_select_mode_two_bt); + button_free(&le_settings_bt); + button_free(&le_bad_bt); + button_free(&le_bkgd_bt); + button_free(&le_fgd_bt); + + if(le_current_level != NULL) + { + level_free_gfx(); + level_free(le_current_level); + unloadshared(); + arrays_free(); + } +} + +void le_drawinterface() +{ + int x,y; + char str[80]; + + if(le_current_level != NULL) + { + /* draw a grid (if selected) */ + if(le_show_grid) + { + for(x = 0; x < 19; x++) + fillrect(x*32 - ((int)pos_x % 32), 0, 1, screen->h, 225, 225, 225,255); + for(y = 0; y < 15; y++) + fillrect(0, y*32, screen->w - 32, 1, 225, 225, 225,255); + } + } + + if(le_selection_mode == CURSOR) + texture_draw(&le_selection, cursor_x - pos_x, cursor_y, NO_UPDATE); + else if(le_selection_mode == SQUARE) + { + int w, h; + le_highlight_selection(); + /* draw current selection */ + w = selection.x2 - selection.x1; + h = selection.y2 - selection.y1; + fillrect(selection.x1 - pos_x, selection.y1, w, SELECT_W, SELECT_CLR); + fillrect(selection.x1 - pos_x + w, selection.y1, SELECT_W, h, SELECT_CLR); + fillrect(selection.x1 - pos_x, selection.y1 + h, w, SELECT_W, SELECT_CLR); + fillrect(selection.x1 - pos_x, selection.y1, SELECT_W, h, SELECT_CLR); + } + + + /* draw button bar */ + fillrect(screen->w - 64, 0, 64, screen->h, 50, 50, 50,255); + drawshape(19 * 32, 14 * 32, le_current_tile); + switch(le_current_tile) + { + case 'B': + texture_draw(&img_mints, 19 * 32, 14 * 32, NO_UPDATE); + break; + case '!': + texture_draw(&img_golden_herring,19 * 32, 14 * 32, NO_UPDATE); + break; + case 'x': + case 'y': + case 'A': + texture_draw(&img_distro[(le_frame / 5) % 4], 19 * 32, 14 * 32, NO_UPDATE); + break; + case '0': + texture_draw(&img_bsod_left[(le_frame / 5) % 4],19 * 32, 14 * 32, NO_UPDATE); + break; + case '1': + texture_draw(&img_laptop_left[(le_frame / 5) % 3],19 * 32, 14 * 32, NO_UPDATE); + break; + case '2': + texture_draw(&img_money_left[0],19 * 32, 14 * 32, NO_UPDATE); + break; + default: + break; + } + + if(le_current_level != NULL) + { + button_draw(&le_save_level_bt); + button_draw(&le_test_level_bt); + button_draw(&le_next_level_bt); + button_draw(&le_previous_level_bt); + button_draw(&le_rubber_bt); + button_draw(&le_select_mode_one_bt); + button_draw(&le_select_mode_two_bt); + button_draw(&le_settings_bt); + button_draw(&le_move_right_bt); + button_draw(&le_move_left_bt); + button_draw(&le_bad_bt); + button_draw(&le_bkgd_bt); + button_draw(&le_fgd_bt); + button_panel_draw(&le_bkgd_panel); + button_panel_draw(&le_fgd_panel); + button_panel_draw(&le_bad_panel); + + sprintf(str, "%d/%d", le_level,le_level_subset.levels); + text_drawf(&white_text, str, -8, 16, A_RIGHT, A_NONE, 1, NO_UPDATE); + + text_draw(&white_small_text, "F1 for Help", 10, 430, 1, NO_UPDATE); + } + else + { + if(show_menu == NO) + text_draw(&white_small_text, "No Level Subset loaded - Press ESC and choose one in the menu", 10, 430, 1, NO_UPDATE); + else + text_draw(&white_small_text, "No Level Subset loaded", 10, 430, 1, NO_UPDATE); + } + +} + +void le_drawlevel() +{ + int y,x,i,s; + static char str[LEVEL_NAME_MAX]; + + /* Draw the real background */ + if(le_current_level->bkgd_image[0] != '\0') + { + s = pos_x / 30; + texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s - 32, img_bkgd.h, NO_UPDATE); + texture_draw_part(&img_bkgd,0,0,screen->w - s - 32 ,0,s,img_bkgd.h, NO_UPDATE); + } + else + { + clearscreen(le_current_level->bkgd_red, le_current_level->bkgd_green, le_current_level->bkgd_blue); + } + + /* clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue); */ + + for (y = 0; y < 15; ++y) + for (x = 0; x < 20; ++x) + { + drawshape(x * 32 - ((int)pos_x % 32), y * 32, le_current_level->tiles[y][x + (int)(pos_x / 32)]); + + /* draw whats inside stuff when cursor is selecting those */ + /* (draw them all the time - is this the right behaviour?) */ + switch(le_current_level->tiles[y][x + (int)(pos_x/32)]) + { + case 'B': + texture_draw(&img_mints, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE); + break; + case '!': + texture_draw(&img_golden_herring, x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE); + break; + case 'x': + case 'y': + case 'A': + texture_draw(&img_distro[(frame / 5) % 4], x * 32 - ((int)pos_x % 32), y*32, NO_UPDATE); + break; + default: + break; + } + } + + /* Draw the Bad guys: */ + for (i = 0; i < num_bad_guys; ++i) + { + if(bad_guys[i].base.alive == NO) + continue; + /* to support frames: img_bsod_left[(frame / 5) % 4] */ + if(bad_guys[i].kind == BAD_BSOD) + texture_draw(&img_bsod_left[(le_frame / 5) % 4], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE); + else if(bad_guys[i].kind == BAD_LAPTOP) + texture_draw(&img_laptop_left[(le_frame / 5) % 3], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE); + else if (bad_guys[i].kind == BAD_MONEY) + texture_draw(&img_money_left[(le_frame / 5) % 2], bad_guys[i].base.x - pos_x, bad_guys[i].base.y, NO_UPDATE); + } + + + /* Draw the player: */ + /* for now, the position is fixed at (0, 240) */ + texture_draw(&tux_right[(frame / 5) % 3], 0 - pos_x, 240, NO_UPDATE); +} + +void le_checkevents() +{ + SDLKey key; + SDLMod keymod; + button_type* pbutton; + int x,y; + + keymod = SDL_GetModState(); + + while(SDL_PollEvent(&event)) + { + /* testing SDL_KEYDOWN, SDL_KEYUP and SDL_QUIT events*/ + if(event.type == SDL_KEYDOWN || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > 0 && event.motion.x < screen->w - 64 && + event.motion.y > 0 && event.motion.y < screen->h))) + { + + switch(event.type) + { + case SDL_KEYDOWN: // key pressed + key = event.key.keysym.sym; + if(show_menu) + { + menu_event(&event.key.keysym); + if(key == SDLK_ESCAPE) + { + show_menu = NO; + menu_set_current(&leveleditor_menu); + } + break; + } + switch(key) + { + case SDLK_ESCAPE: + if(!show_menu) + show_menu = YES; + else + show_menu = NO; + break; + case SDLK_LEFT: + if(fire == DOWN) + cursor_x -= KEY_CURSOR_SPEED; + else + cursor_x -= KEY_CURSOR_FASTSPEED; + + if(cursor_x < pos_x + MOUSE_LEFT_MARGIN) + pos_x = cursor_x - MOUSE_LEFT_MARGIN; + + break; + case SDLK_RIGHT: + if(fire == DOWN) + cursor_x += KEY_CURSOR_SPEED; + else + cursor_x += KEY_CURSOR_FASTSPEED; + + if(cursor_x > pos_x + MOUSE_RIGHT_MARGIN-32) + pos_x = cursor_x - MOUSE_RIGHT_MARGIN+32; + + break; + case SDLK_UP: + if(fire == DOWN) + cursor_y -= KEY_CURSOR_SPEED; + else + cursor_y -= KEY_CURSOR_FASTSPEED; + + if(cursor_y < 0) + cursor_y = 0; + break; + case SDLK_DOWN: + if(fire == DOWN) + cursor_y += KEY_CURSOR_SPEED; + else + cursor_y += KEY_CURSOR_FASTSPEED; + + if(cursor_y > screen->h-32) + cursor_y = screen->h-32; + break; + case SDLK_LCTRL: + fire =UP; + break; + case SDLK_F1: + le_showhelp(); + break; + case SDLK_HOME: + cursor_x = 0; + pos_x = cursor_x; + break; + case SDLK_END: + cursor_x = (le_current_level->width * 32) - 32; + pos_x = cursor_x; + break; + case SDLK_F9: + le_show_grid = !le_show_grid; + break; + default: + break; + } + break; + case SDL_KEYUP: /* key released */ + switch(event.key.keysym.sym) + { + case SDLK_LCTRL: + fire = DOWN; + break; + default: + break; + } + break; + case SDL_MOUSEBUTTONDOWN: + if(event.button.button == SDL_BUTTON_LEFT) + { + le_mouse_pressed[LEFT] = YES; + + selection.x1 = event.motion.x + pos_x; + selection.y1 = event.motion.y; + selection.x2 = event.motion.x + pos_x; + selection.y2 = event.motion.y; + } + else if(event.button.button == SDL_BUTTON_RIGHT) + le_mouse_pressed[RIGHT] = YES; + break; + case SDL_MOUSEBUTTONUP: + if(event.button.button == SDL_BUTTON_LEFT) + le_mouse_pressed[LEFT] = NO; + else if(event.button.button == SDL_BUTTON_RIGHT) + le_mouse_pressed[RIGHT] = NO; + break; + case SDL_MOUSEMOTION: + if(!show_menu) + { + x = event.motion.x; + y = event.motion.y; + + cursor_x = ((int)(pos_x + x) / 32) * 32; + cursor_y = ((int) y / 32) * 32; + + if(le_mouse_pressed[LEFT] == YES) + { + selection.x2 = x + pos_x; + selection.y2 = y; + } + + if(le_mouse_pressed[RIGHT] == YES) + { + pos_x += -1 * event.motion.xrel; + } + } + break; + case SDL_QUIT: // window closed + done = DONE_QUIT; + break; + default: + break; + } + } + + if(le_current_level != NULL) + { + if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP || ((event.type == SDL_MOUSEBUTTONDOWN || SDL_MOUSEMOTION) && (event.motion.x > screen->w-64 && event.motion.x < screen->w && + event.motion.y > 0 && event.motion.y < screen->h))) + { + le_mouse_pressed[LEFT] = NO; + le_mouse_pressed[RIGHT] = NO; + + if(show_menu == NO) + { + /* Check for button events */ + button_event(&le_test_level_bt,&event); + if(button_get_state(&le_test_level_bt) == BN_CLICKED) + le_testlevel(); + button_event(&le_save_level_bt,&event); + if(button_get_state(&le_save_level_bt) == BN_CLICKED) + level_save(le_current_level,le_level_subset.name,le_level); + button_event(&le_next_level_bt,&event); + if(button_get_state(&le_next_level_bt) == BN_CLICKED) + { + if(le_level < le_level_subset.levels) + { + le_goto_level(++le_level); + } + else + { + st_level new_lev; + char str[1024]; + int d = 0; + sprintf(str,"Level %d doesn't exist.",le_level+1); + text_drawf(&white_text,str,0,-18,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE); + text_drawf(&white_text,"Do you want to create it?",0,0,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE); + text_drawf(&red_text,"(Y)es/(N)o",0,20,A_HMIDDLE,A_VMIDDLE,2,NO_UPDATE); + flipscreen(); + while(d == 0) + { + while(SDL_PollEvent(&event)) + switch(event.type) + { + case SDL_KEYDOWN: // key pressed + switch(event.key.keysym.sym) + { + case SDLK_y: + le_default_level(&new_lev); + level_save(&new_lev,le_level_subset.name,++le_level); + le_level_subset.levels = le_level; + le_goto_level(le_level); + d = 1; + break; + case SDLK_n: + d = 1; + break; + } + break; + default: + break; + } + SDL_Delay(50); + } + } + } + button_event(&le_previous_level_bt,&event); + if(button_get_state(&le_previous_level_bt) == BN_CLICKED) + { + if(le_level > 1) + le_goto_level(--le_level); + } + button_event(&le_rubber_bt,&event); + if(button_get_state(&le_rubber_bt) == BN_CLICKED) + le_current_tile = '.'; + button_event(&le_select_mode_one_bt,&event); + if(button_get_state(&le_select_mode_one_bt) == BN_CLICKED) + le_selection_mode = CURSOR; + button_event(&le_select_mode_two_bt,&event); + if(button_get_state(&le_select_mode_two_bt) == BN_CLICKED) + le_selection_mode = SQUARE; + + button_event(&le_bad_bt,&event); + if(button_get_state(&le_bad_bt) == BN_CLICKED) + { + le_bad_panel.hidden = NO; + le_fgd_panel.hidden = YES; + le_bkgd_panel.hidden = YES; + } + + button_event(&le_fgd_bt,&event); + if(button_get_state(&le_fgd_bt) == BN_CLICKED) + { + le_bad_panel.hidden = YES; + le_fgd_panel.hidden = NO; + le_bkgd_panel.hidden = YES; + } + button_event(&le_bkgd_bt,&event); + if(button_get_state(&le_bkgd_bt) == BN_CLICKED) + { + le_bad_panel.hidden = YES; + le_fgd_panel.hidden = YES; + le_bkgd_panel.hidden = NO; + } + button_event(&le_settings_bt,&event); + if(button_get_state(&le_settings_bt) == BN_CLICKED) + { + if(show_menu == NO) + { + update_level_settings_menu(); + menu_set_current(&level_settings_menu); + show_menu = YES; + } + else + { + menu_set_current(&leveleditor_menu); + show_menu = NO; + } + } + if((pbutton = button_panel_event(&le_bkgd_panel,&event)) != NULL) + { + if(button_get_state(pbutton) == BN_CLICKED) + { + char c = '\0'; + if(pbutton->tag >= 0 && pbutton->tag <= 3) + c = 'G' + pbutton->tag; + else if(pbutton->tag >= 4 && pbutton->tag <= 7) + c = 'g' + pbutton->tag - 4; + else if(pbutton->tag >= 8 && pbutton->tag <= 11) + c = 'C' + pbutton->tag - 8; + else if(pbutton->tag >= 12 && pbutton->tag <= 15) + c = 'c' + pbutton->tag - 12; + if(c != '\0') + le_current_tile = c; + } + } + if((pbutton = button_panel_event(&le_fgd_panel,&event)) != NULL) + { + if(button_get_state(pbutton) == BN_CLICKED) + { + char c = '\0'; + if(pbutton->tag == 0) + c = '#' ; + else if(pbutton->tag == 1) + c = '['; + else if(pbutton->tag == 2) + c = '='; + else if(pbutton->tag == 3) + c = ']'; + else if(pbutton->tag == 4) + c = '^'; + else if(pbutton->tag == 5) + c = '&'; + else if(pbutton->tag == 6) + c = '|'; + else if(pbutton->tag == 7) + c = '*'; + else if(pbutton->tag == 8) + c = '\\'; + else if(pbutton->tag == 9) + c = 'a'; + else if(pbutton->tag == 10) + c = 'B'; + else if(pbutton->tag == 11) + c = 'A'; + else if(pbutton->tag == 12) + c = '!'; + else if(pbutton->tag == 13) + c = '$'; + else if(pbutton->tag == 14) + c = 'X'; + else if(pbutton->tag == 15) + c = 'Y'; + else if(pbutton->tag == 16) + c = 'x'; + else if(pbutton->tag == 17) + c = 'y'; + if(c != '\0') + le_current_tile = c; + } + } + if((pbutton = button_panel_event(&le_bad_panel,&event)) != NULL) + { + if(button_get_state(pbutton) == BN_CLICKED) + { + char c = '\0'; + if(pbutton->tag >= 0 && pbutton->tag <= 2) + c = '0' + pbutton->tag; + if(c != '\0') + le_current_tile = c; + } + } + } + else + { + button_event(&le_settings_bt,&event); + if(button_get_state(&le_settings_bt) == BN_CLICKED) + { + if(show_menu == NO) + { + update_level_settings_menu(); + menu_set_current(&level_settings_menu); + show_menu = YES; + } + else + { + menu_set_current(&leveleditor_menu); + show_menu = NO; + } + } + } + } + if(show_menu == NO) + { + button_event(&le_move_left_bt,&event); + button_event(&le_move_right_bt,&event); + + if(le_mouse_pressed[LEFT]) + { + le_change(cursor_x, cursor_y, le_current_tile); + } + } + } + } + if(show_menu == NO) + { + if(button_get_state(&le_move_left_bt) == BN_PRESSED) + { + pos_x -= 192; + } + else if(button_get_state(&le_move_left_bt) == BN_HOVER) + { + pos_x -= 96; + } + + if(button_get_state(&le_move_right_bt) == BN_PRESSED) + { + pos_x += 192; + } + else if(button_get_state(&le_move_right_bt) == BN_HOVER) + { + pos_x += 96; + } + } + +} + +void le_highlight_selection() +{ + int x,y,i; + int x1, x2, y1, y2; + + if(selection.x1 < selection.x2) + { + x1 = selection.x1; + x2 = selection.x2; + } + else + { + x1 = selection.x2; + x2 = selection.x1; + } + if(selection.y1 < selection.y2) + { + y1 = selection.y1; + y2 = selection.y2; + } + else + { + y1 = selection.y2; + y2 = selection.y1; + } + + x1 /= 32; + x2 /= 32; + y1 /= 32; + y2 /= 32; + + fillrect(x1*32-pos_x, y1*32,32* (x2 - x1 + 1),32 * (y2 - y1 + 1),173,234,177,103); +} + +void le_change(float x, float y, unsigned char c) +{ + if(le_current_level != NULL) + { + int xx,yy,i; + int x1, x2, y1, y2; + + /* level_changed = YES; */ + + switch(le_selection_mode) + { + case CURSOR: + level_change(le_current_level,x,y,c); + + yy = ((int)y / 32); + xx = ((int)x / 32); + + /* if there is a bad guy over there, remove it */ + for(i = 0; i < num_bad_guys; ++i) + if (bad_guys[i].base.alive) + if(xx == bad_guys[i].base.x/32 && yy == bad_guys[i].base.y/32) + bad_guys[i].base.alive = NO; + + if(c == '0') /* if it's a bad guy */ + add_bad_guy(xx*32, yy*32, BAD_BSOD); + else if(c == '1') + add_bad_guy(xx*32, yy*32, BAD_LAPTOP); + else if(c == '2') + add_bad_guy(xx*32, yy*32, BAD_MONEY); + + break; + case SQUARE: + if(selection.x1 < selection.x2) + { + x1 = selection.x1; + x2 = selection.x2; + } + else + { + x1 = selection.x2; + x2 = selection.x1; + } + if(selection.y1 < selection.y2) + { + y1 = selection.y1; + y2 = selection.y2; + } + else + { + y1 = selection.y2; + y2 = selection.y1; + } + + x1 /= 32; + x2 /= 32; + y1 /= 32; + y2 /= 32; + + /* if there is a bad guy over there, remove it */ + for(i = 0; i < num_bad_guys; ++i) + if(bad_guys[i].base.alive) + if(bad_guys[i].base.x/32 >= x1 && bad_guys[i].base.x/32 <= x2 + && bad_guys[i].base.y/32 >= y1 && bad_guys[i].base.y/32 <= y2) + bad_guys[i].base.alive = NO; + + for(xx = x1; xx <= x2; xx++) + for(yy = y1; yy <= y2; yy++) + { + level_change(le_current_level, xx*32, yy*32, c); + + if(c == '0') // if it's a bad guy + add_bad_guy(xx*32, yy*32, BAD_BSOD); + else if(c == '1') + add_bad_guy(xx*32, yy*32, BAD_LAPTOP); + else if(c == '2') + add_bad_guy(xx*32, yy*32, BAD_MONEY); + } + break; + default: + break; + } + } +} + +void le_testlevel() +{ + level_save(le_current_level,"test",le_level); + gameloop("test",le_level, ST_GL_TEST); + menu_set_current(&leveleditor_menu); + arrays_init(); + level_load_gfx(le_current_level); + loadshared(); + le_activate_bad_guys(); +} + +void le_showhelp() +{ + SDL_Event event; + int i, done; + char *text[] = { + " - This is SuperTux's built-in level editor -", + "It has been designed to be light and easy to use from the start.", + "", + "When you first load the level editor you are given a menu where you", + "can load level subsets, create a new level subset, edit the current", + "subset's settings, or simply quit the editor. You can access this menu", + "from the level editor at any time by pressing the escape key.", + "", + "To your right is your button bar. The center of this contains many", + "tiles you can use to make your level. To select a tile, click on it", + "with your left mouse button; your selection will be shown in the", + "bottom right corner of the button box. Click anywhere on your level", + "with the left mouse button to place that tile down. If you right click", + "a tile in the button bar, you can find out what its keyboard shortcut", + "is. The three buttons FGD, BGD and EMY let you pick from foreground,", + "background, and enemy tiles. The eraser lets you remove tiles.", + "The left and right arrow keys scroll back and forth through your level.", + "The button with the wrench and screwdriver, lets you change the", + "settings of your level, including how long it is or what music it will", + "play. When you are ready to give your level a test, click on the little", + "running Tux. If you like the changes you have made to your level,", + "press the red save key to keep them.", + "To change which level in your subset you are editing, press the white", + "up and down arrow keys at the top of the button box.", + "", + "Have fun making levels! If you make some good ones, send them to us on", + "the SuperTux mailing list!", + "- SuperTux team" + }; + + + text_drawf(&blue_text, "- Help -", 0, 30, A_HMIDDLE, A_TOP, 2, NO_UPDATE); + + for(i = 0; i < sizeof(text)/sizeof(char *); i++) + text_draw(&white_small_text, text[i], 5, 80+(i*12), 1, NO_UPDATE); + + text_drawf(&gold_text, "Press Any Key to Continue", 0, 440, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + + flipscreen(); + + done = 0; + + while(done == 0) + { + while(SDL_PollEvent(&event)) + switch(event.type) + { + case SDL_MOUSEBUTTONDOWN: // mouse pressed + case SDL_KEYDOWN: // key pressed + done = 1; + break; + default: + break; + } + SDL_Delay(50); + } +} diff --git a/src/lispreader.c b/src/lispreader.c deleted file mode 100644 index 80be35c00..000000000 --- a/src/lispreader.c +++ /dev/null @@ -1,985 +0,0 @@ -/* $Id$ */ -/* - * lispreader.c - * - * Copyright (C) 1998-2000 Mark Probst - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include - -#include - -#define TOKEN_ERROR -1 -#define TOKEN_EOF 0 -#define TOKEN_OPEN_PAREN 1 -#define TOKEN_CLOSE_PAREN 2 -#define TOKEN_SYMBOL 3 -#define TOKEN_STRING 4 -#define TOKEN_INTEGER 5 -#define TOKEN_REAL 6 -#define TOKEN_PATTERN_OPEN_PAREN 7 -#define TOKEN_DOT 8 -#define TOKEN_TRUE 9 -#define TOKEN_FALSE 10 - - -#define MAX_TOKEN_LENGTH 1024 - -static char token_string[MAX_TOKEN_LENGTH + 1] = ""; -static int token_length = 0; - -static lisp_object_t end_marker = { LISP_TYPE_EOF }; -static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR }; -static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR }; -static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR }; - -static void -_token_clear (void) -{ - token_string[0] = '\0'; - token_length = 0; -} - -static void -_token_append (char c) -{ - assert(token_length < MAX_TOKEN_LENGTH); - - token_string[token_length++] = c; - token_string[token_length] = '\0'; -} - -static int -_next_char (lisp_stream_t *stream) -{ - switch (stream->type) - { - case LISP_STREAM_FILE : - return getc(stream->v.file); - - case LISP_STREAM_STRING : - { - char c = stream->v.string.buf[stream->v.string.pos]; - - if (c == 0) - return EOF; - - ++stream->v.string.pos; - - return c; - } - - case LISP_STREAM_ANY: - return stream->v.any.next_char(stream->v.any.data); - } - assert(0); - return EOF; -} - -static void -_unget_char (char c, lisp_stream_t *stream) -{ - switch (stream->type) - { - case LISP_STREAM_FILE : - ungetc(c, stream->v.file); - break; - - case LISP_STREAM_STRING : - --stream->v.string.pos; - break; - - case LISP_STREAM_ANY: - stream->v.any.unget_char(c, stream->v.any.data); - break; - - default : - assert(0); - } -} - -static int -_scan (lisp_stream_t *stream) -{ - static char *delims = "\"();"; - - int c; - - _token_clear(); - - do - { - c = _next_char(stream); - if (c == EOF) - return TOKEN_EOF; - else if (c == ';') /* comment start */ - while (1) - { - c = _next_char(stream); - if (c == EOF) - return TOKEN_EOF; - else if (c == '\n') - break; - } - } while (isspace(c)); - - switch (c) - { - case '(' : - return TOKEN_OPEN_PAREN; - - case ')' : - return TOKEN_CLOSE_PAREN; - - case '"' : - while (1) - { - c = _next_char(stream); - if (c == EOF) - return TOKEN_ERROR; - if (c == '"') - break; - if (c == '\\') - { - c = _next_char(stream); - - switch (c) - { - case EOF : - return TOKEN_ERROR; - - case 'n' : - c = '\n'; - break; - - case 't' : - c = '\t'; - break; - } - } - - _token_append(c); - } - return TOKEN_STRING; - - case '#' : - c = _next_char(stream); - if (c == EOF) - return TOKEN_ERROR; - - switch (c) - { - case 't' : - return TOKEN_TRUE; - - case 'f' : - return TOKEN_FALSE; - - case '?' : - c = _next_char(stream); - if (c == EOF) - return TOKEN_ERROR; - - if (c == '(') - return TOKEN_PATTERN_OPEN_PAREN; - else - return TOKEN_ERROR; - } - return TOKEN_ERROR; - - default : - if (isdigit(c) || c == '-') - { - int have_nondigits = 0; - int have_digits = 0; - int have_floating_point = 0; - - do - { - if (isdigit(c)) - have_digits = 1; - else if (c == '.') - have_floating_point++; - _token_append(c); - - c = _next_char(stream); - - if (c != EOF && !isdigit(c) && !isspace(c) && c != '.' && !strchr(delims, c)) - have_nondigits = 1; - } while (c != EOF && !isspace(c) && !strchr(delims, c)); - - if (c != EOF) - _unget_char(c, stream); - - if (have_nondigits || !have_digits || have_floating_point > 1) - return TOKEN_SYMBOL; - else if (have_floating_point == 1) - return TOKEN_REAL; - else - return TOKEN_INTEGER; - } - else - { - if (c == '.') - { - c = _next_char(stream); - if (c != EOF && !isspace(c) && !strchr(delims, c)) - _token_append('.'); - else - { - _unget_char(c, stream); - return TOKEN_DOT; - } - } - do - { - _token_append(c); - c = _next_char(stream); - } while (c != EOF && !isspace(c) && !strchr(delims, c)); - if (c != EOF) - _unget_char(c, stream); - - return TOKEN_SYMBOL; - } - } - - assert(0); - return TOKEN_ERROR; -} - -static lisp_object_t* -lisp_object_alloc (int type) -{ - lisp_object_t *obj = (lisp_object_t*)malloc(sizeof(lisp_object_t)); - - obj->type = type; - - return obj; -} - -lisp_stream_t* -lisp_stream_init_file (lisp_stream_t *stream, FILE *file) -{ - stream->type = LISP_STREAM_FILE; - stream->v.file = file; - - return stream; -} - -lisp_stream_t* -lisp_stream_init_string (lisp_stream_t *stream, char *buf) -{ - stream->type = LISP_STREAM_STRING; - stream->v.string.buf = buf; - stream->v.string.pos = 0; - - return stream; -} - -lisp_stream_t* -lisp_stream_init_any (lisp_stream_t *stream, void *data, - int (*next_char) (void *data), - void (*unget_char) (char c, void *data)) -{ - assert(next_char != 0 && unget_char != 0); - - stream->type = LISP_STREAM_ANY; - stream->v.any.data = data; - stream->v.any.next_char= next_char; - stream->v.any.unget_char = unget_char; - - return stream; -} - -lisp_object_t* -lisp_make_integer (int value) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_INTEGER); - - obj->v.integer = value; - - return obj; -} - -lisp_object_t* -lisp_make_real (float value) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_REAL); - - obj->v.real = value; - - return obj; -} - -lisp_object_t* -lisp_make_symbol (const char *value) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_SYMBOL); - - obj->v.string = strdup(value); - - return obj; -} - -lisp_object_t* -lisp_make_string (const char *value) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_STRING); - - obj->v.string = strdup(value); - - return obj; -} - -lisp_object_t* -lisp_make_cons (lisp_object_t *car, lisp_object_t *cdr) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_CONS); - - obj->v.cons.car = car; - obj->v.cons.cdr = cdr; - - return obj; -} - -lisp_object_t* -lisp_make_boolean (int value) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_BOOLEAN); - - obj->v.integer = value ? 1 : 0; - - return obj; -} - -static lisp_object_t* -lisp_make_pattern_cons (lisp_object_t *car, lisp_object_t *cdr) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_CONS); - - obj->v.cons.car = car; - obj->v.cons.cdr = cdr; - - return obj; -} - -static lisp_object_t* -lisp_make_pattern_var (int type, int index, lisp_object_t *sub) -{ - lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_VAR); - - obj->v.pattern.type = type; - obj->v.pattern.index = index; - obj->v.pattern.sub = sub; - - return obj; -} - -lisp_object_t* -lisp_read (lisp_stream_t *in) -{ - int token = _scan(in); - lisp_object_t *obj = lisp_nil(); - - if (token == TOKEN_EOF) - return &end_marker; - - switch (token) - { - case TOKEN_ERROR : - return &error_object; - - case TOKEN_EOF : - return &end_marker; - - case TOKEN_OPEN_PAREN : - case TOKEN_PATTERN_OPEN_PAREN : - { - lisp_object_t *last = lisp_nil(), *car; - - do - { - car = lisp_read(in); - if (car == &error_object || car == &end_marker) - { - lisp_free(obj); - return &error_object; - } - else if (car == &dot_marker) - { - if (lisp_nil_p(last)) - { - lisp_free(obj); - return &error_object; - } - - car = lisp_read(in); - if (car == &error_object || car == &end_marker) - { - lisp_free(obj); - return car; - } - else - { - last->v.cons.cdr = car; - - if (_scan(in) != TOKEN_CLOSE_PAREN) - { - lisp_free(obj); - return &error_object; - } - - car = &close_paren_marker; - } - } - else if (car != &close_paren_marker) - { - if (lisp_nil_p(last)) - obj = last = (token == TOKEN_OPEN_PAREN ? lisp_make_cons(car, lisp_nil()) : lisp_make_pattern_cons(car, lisp_nil())); - else - last = last->v.cons.cdr = lisp_make_cons(car, lisp_nil()); - } - } while (car != &close_paren_marker); - } - return obj; - - case TOKEN_CLOSE_PAREN : - return &close_paren_marker; - - case TOKEN_SYMBOL : - return lisp_make_symbol(token_string); - - case TOKEN_STRING : - return lisp_make_string(token_string); - - case TOKEN_INTEGER : - return lisp_make_integer(atoi(token_string)); - - case TOKEN_REAL : - return lisp_make_real((float)atof(token_string)); - - case TOKEN_DOT : - return &dot_marker; - - case TOKEN_TRUE : - return lisp_make_boolean(1); - - case TOKEN_FALSE : - return lisp_make_boolean(0); - } - - assert(0); - return &error_object; -} - -void -lisp_free (lisp_object_t *obj) -{ - if (obj == 0) - return; - - switch (obj->type) - { - case LISP_TYPE_INTERNAL : - case LISP_TYPE_PARSE_ERROR : - case LISP_TYPE_EOF : - return; - - case LISP_TYPE_SYMBOL : - case LISP_TYPE_STRING : - free(obj->v.string); - break; - - case LISP_TYPE_CONS : - case LISP_TYPE_PATTERN_CONS : - lisp_free(obj->v.cons.car); - lisp_free(obj->v.cons.cdr); - break; - - case LISP_TYPE_PATTERN_VAR : - lisp_free(obj->v.pattern.sub); - break; - } - - free(obj); -} - -lisp_object_t* -lisp_read_from_string (const char *buf) -{ - lisp_stream_t stream; - - lisp_stream_init_string(&stream, (char*)buf); - return lisp_read(&stream); -} - -static int -_compile_pattern (lisp_object_t **obj, int *index) -{ - if (*obj == 0) - return 1; - - switch (lisp_type(*obj)) - { - case LISP_TYPE_PATTERN_CONS : - { - struct { char *name; int type; } types[] = - { - { "any", LISP_PATTERN_ANY }, - { "symbol", LISP_PATTERN_SYMBOL }, - { "string", LISP_PATTERN_STRING }, - { "integer", LISP_PATTERN_INTEGER }, - { "real", LISP_PATTERN_REAL }, - { "boolean", LISP_PATTERN_BOOLEAN }, - { "list", LISP_PATTERN_LIST }, - { "or", LISP_PATTERN_OR }, - { 0, 0 } - }; - char *type_name; - int type; - int i; - lisp_object_t *pattern; - - if (lisp_type(lisp_car(*obj)) != LISP_TYPE_SYMBOL) - return 0; - - type_name = lisp_symbol(lisp_car(*obj)); - for (i = 0; types[i].name != 0; ++i) - { - if (strcmp(types[i].name, type_name) == 0) - { - type = types[i].type; - break; - } - } - - if (types[i].name == 0) - return 0; - - if (type != LISP_PATTERN_OR && lisp_cdr(*obj) != 0) - return 0; - - pattern = lisp_make_pattern_var(type, (*index)++, lisp_nil()); - - if (type == LISP_PATTERN_OR) - { - lisp_object_t *cdr = lisp_cdr(*obj); - - if (!_compile_pattern(&cdr, index)) - { - lisp_free(pattern); - return 0; - } - - pattern->v.pattern.sub = cdr; - - (*obj)->v.cons.cdr = lisp_nil(); - } - - lisp_free(*obj); - - *obj = pattern; - } - break; - - case LISP_TYPE_CONS : - if (!_compile_pattern(&(*obj)->v.cons.car, index)) - return 0; - if (!_compile_pattern(&(*obj)->v.cons.cdr, index)) - return 0; - break; - } - - return 1; -} - -int -lisp_compile_pattern (lisp_object_t **obj, int *num_subs) -{ - int index = 0; - int result; - - result = _compile_pattern(obj, &index); - - if (result && num_subs != 0) - *num_subs = index; - - return result; -} - -static int _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars); - -static int -_match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars) -{ - assert(lisp_type(pattern) == LISP_TYPE_PATTERN_VAR); - - switch (pattern->v.pattern.type) - { - case LISP_PATTERN_ANY : - break; - - case LISP_PATTERN_SYMBOL : - if (obj == 0 || lisp_type(obj) != LISP_TYPE_SYMBOL) - return 0; - break; - - case LISP_PATTERN_STRING : - if (obj == 0 || lisp_type(obj) != LISP_TYPE_STRING) - return 0; - break; - - case LISP_PATTERN_INTEGER : - if (obj == 0 || lisp_type(obj) != LISP_TYPE_INTEGER) - return 0; - break; - - case LISP_PATTERN_REAL : - if (obj == 0 || lisp_type(obj) != LISP_TYPE_REAL) - return 0; - break; - - case LISP_PATTERN_BOOLEAN : - if (obj == 0 || lisp_type(obj) != LISP_TYPE_BOOLEAN) - return 0; - break; - - case LISP_PATTERN_LIST : - if (obj == 0 || lisp_type(obj) != LISP_TYPE_CONS) - return 0; - break; - - case LISP_PATTERN_OR : - { - lisp_object_t *sub; - int matched = 0; - - for (sub = pattern->v.pattern.sub; sub != 0; sub = lisp_cdr(sub)) - { - assert(lisp_type(sub) == LISP_TYPE_CONS); - - if (_match_pattern(lisp_car(sub), obj, vars)) - matched = 1; - } - - if (!matched) - return 0; - } - break; - - default : - assert(0); - } - - if (vars != 0) - vars[pattern->v.pattern.index] = obj; - - return 1; -} - -static int -_match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars) -{ - if (pattern == 0) - return obj == 0; - - if (obj == 0) - return 0; - - if (lisp_type(pattern) == LISP_TYPE_PATTERN_VAR) - return _match_pattern_var(pattern, obj, vars); - - if (lisp_type(pattern) != lisp_type(obj)) - return 0; - - switch (lisp_type(pattern)) - { - case LISP_TYPE_SYMBOL : - return strcmp(lisp_symbol(pattern), lisp_symbol(obj)) == 0; - - case LISP_TYPE_STRING : - return strcmp(lisp_string(pattern), lisp_string(obj)) == 0; - - case LISP_TYPE_INTEGER : - return lisp_integer(pattern) == lisp_integer(obj); - - case LISP_TYPE_REAL : - return lisp_real(pattern) == lisp_real(obj); - - case LISP_TYPE_CONS : - { - int result1, result2; - - result1 = _match_pattern(lisp_car(pattern), lisp_car(obj), vars); - result2 = _match_pattern(lisp_cdr(pattern), lisp_cdr(obj), vars); - - return result1 && result2; - } - break; - - default : - assert(0); - } - - return 0; -} - -int -lisp_match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars, int num_subs) -{ - int i; - - if (vars != 0) - for (i = 0; i < num_subs; ++i) - vars[i] = &error_object; - - return _match_pattern(pattern, obj, vars); -} - -int -lisp_match_string (const char *pattern_string, lisp_object_t *obj, lisp_object_t **vars) -{ - lisp_object_t *pattern; - int result; - int num_subs; - - pattern = lisp_read_from_string(pattern_string); - - if (pattern != 0 && (lisp_type(pattern) == LISP_TYPE_EOF - || lisp_type(pattern) == LISP_TYPE_PARSE_ERROR)) - return 0; - - if (!lisp_compile_pattern(&pattern, &num_subs)) - { - lisp_free(pattern); - return 0; - } - - result = lisp_match_pattern(pattern, obj, vars, num_subs); - - lisp_free(pattern); - - return result; -} - -int -lisp_type (lisp_object_t *obj) -{ - if (obj == 0) - return LISP_TYPE_NIL; - return obj->type; -} - -int -lisp_integer (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_INTEGER); - - return obj->v.integer; -} - -char* -lisp_symbol (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_SYMBOL); - - return obj->v.string; -} - -char* -lisp_string (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_STRING); - - return obj->v.string; -} - -int -lisp_boolean (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_BOOLEAN); - - return obj->v.integer; -} - -float -lisp_real (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_REAL || obj->type == LISP_TYPE_INTEGER); - - if (obj->type == LISP_TYPE_INTEGER) - return obj->v.integer; - return obj->v.real; -} - -lisp_object_t* -lisp_car (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); - - return obj->v.cons.car; -} - -lisp_object_t* -lisp_cdr (lisp_object_t *obj) -{ - assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); - - return obj->v.cons.cdr; -} - -lisp_object_t* -lisp_cxr (lisp_object_t *obj, const char *x) -{ - int i; - - for (i = strlen(x) - 1; i >= 0; --i) - if (x[i] == 'a') - obj = lisp_car(obj); - else if (x[i] == 'd') - obj = lisp_cdr(obj); - else - assert(0); - - return obj; -} - -int -lisp_list_length (lisp_object_t *obj) -{ - int length = 0; - - while (obj != 0) - { - assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); - - ++length; - obj = obj->v.cons.cdr; - } - - return length; -} - -lisp_object_t* -lisp_list_nth_cdr (lisp_object_t *obj, int index) -{ - while (index > 0) - { - assert(obj != 0); - assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); - - --index; - obj = obj->v.cons.cdr; - } - - return obj; -} - -lisp_object_t* -lisp_list_nth (lisp_object_t *obj, int index) -{ - obj = lisp_list_nth_cdr(obj, index); - - assert(obj != 0); - - return obj->v.cons.car; -} - -void -lisp_dump (lisp_object_t *obj, FILE *out) -{ - if (obj == 0) - { - fprintf(out, "()"); - return; - } - - switch (lisp_type(obj)) - { - case LISP_TYPE_EOF : - fputs("#", out); - break; - - case LISP_TYPE_PARSE_ERROR : - fputs("#", out); - break; - - case LISP_TYPE_INTEGER : - fprintf(out, "%d", lisp_integer(obj)); - break; - - case LISP_TYPE_REAL : - fprintf(out, "%f", lisp_real(obj)); - break; - - case LISP_TYPE_SYMBOL : - fputs(lisp_symbol(obj), out); - break; - - case LISP_TYPE_STRING : - { - char *p; - - fputc('"', out); - for (p = lisp_string(obj); *p != 0; ++p) - { - if (*p == '"' || *p == '\\') - fputc('\\', out); - fputc(*p, out); - } - fputc('"', out); - } - break; - - case LISP_TYPE_CONS : - case LISP_TYPE_PATTERN_CONS : - fputs(lisp_type(obj) == LISP_TYPE_CONS ? "(" : "#?(", out); - while (obj != 0) - { - lisp_dump(lisp_car(obj), out); - obj = lisp_cdr(obj); - if (obj != 0) - { - if (lisp_type(obj) != LISP_TYPE_CONS - && lisp_type(obj) != LISP_TYPE_PATTERN_CONS) - { - fputs(" . ", out); - lisp_dump(obj, out); - break; - } - else - fputc(' ', out); - } - } - fputc(')', out); - break; - - case LISP_TYPE_BOOLEAN : - if (lisp_boolean(obj)) - fputs("#t", out); - else - fputs("#f", out); - break; - - default : - assert(0); - } -} diff --git a/src/lispreader.cpp b/src/lispreader.cpp new file mode 100644 index 000000000..80be35c00 --- /dev/null +++ b/src/lispreader.cpp @@ -0,0 +1,985 @@ +/* $Id$ */ +/* + * lispreader.c + * + * Copyright (C) 1998-2000 Mark Probst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + +#define TOKEN_ERROR -1 +#define TOKEN_EOF 0 +#define TOKEN_OPEN_PAREN 1 +#define TOKEN_CLOSE_PAREN 2 +#define TOKEN_SYMBOL 3 +#define TOKEN_STRING 4 +#define TOKEN_INTEGER 5 +#define TOKEN_REAL 6 +#define TOKEN_PATTERN_OPEN_PAREN 7 +#define TOKEN_DOT 8 +#define TOKEN_TRUE 9 +#define TOKEN_FALSE 10 + + +#define MAX_TOKEN_LENGTH 1024 + +static char token_string[MAX_TOKEN_LENGTH + 1] = ""; +static int token_length = 0; + +static lisp_object_t end_marker = { LISP_TYPE_EOF }; +static lisp_object_t error_object = { LISP_TYPE_PARSE_ERROR }; +static lisp_object_t close_paren_marker = { LISP_TYPE_PARSE_ERROR }; +static lisp_object_t dot_marker = { LISP_TYPE_PARSE_ERROR }; + +static void +_token_clear (void) +{ + token_string[0] = '\0'; + token_length = 0; +} + +static void +_token_append (char c) +{ + assert(token_length < MAX_TOKEN_LENGTH); + + token_string[token_length++] = c; + token_string[token_length] = '\0'; +} + +static int +_next_char (lisp_stream_t *stream) +{ + switch (stream->type) + { + case LISP_STREAM_FILE : + return getc(stream->v.file); + + case LISP_STREAM_STRING : + { + char c = stream->v.string.buf[stream->v.string.pos]; + + if (c == 0) + return EOF; + + ++stream->v.string.pos; + + return c; + } + + case LISP_STREAM_ANY: + return stream->v.any.next_char(stream->v.any.data); + } + assert(0); + return EOF; +} + +static void +_unget_char (char c, lisp_stream_t *stream) +{ + switch (stream->type) + { + case LISP_STREAM_FILE : + ungetc(c, stream->v.file); + break; + + case LISP_STREAM_STRING : + --stream->v.string.pos; + break; + + case LISP_STREAM_ANY: + stream->v.any.unget_char(c, stream->v.any.data); + break; + + default : + assert(0); + } +} + +static int +_scan (lisp_stream_t *stream) +{ + static char *delims = "\"();"; + + int c; + + _token_clear(); + + do + { + c = _next_char(stream); + if (c == EOF) + return TOKEN_EOF; + else if (c == ';') /* comment start */ + while (1) + { + c = _next_char(stream); + if (c == EOF) + return TOKEN_EOF; + else if (c == '\n') + break; + } + } while (isspace(c)); + + switch (c) + { + case '(' : + return TOKEN_OPEN_PAREN; + + case ')' : + return TOKEN_CLOSE_PAREN; + + case '"' : + while (1) + { + c = _next_char(stream); + if (c == EOF) + return TOKEN_ERROR; + if (c == '"') + break; + if (c == '\\') + { + c = _next_char(stream); + + switch (c) + { + case EOF : + return TOKEN_ERROR; + + case 'n' : + c = '\n'; + break; + + case 't' : + c = '\t'; + break; + } + } + + _token_append(c); + } + return TOKEN_STRING; + + case '#' : + c = _next_char(stream); + if (c == EOF) + return TOKEN_ERROR; + + switch (c) + { + case 't' : + return TOKEN_TRUE; + + case 'f' : + return TOKEN_FALSE; + + case '?' : + c = _next_char(stream); + if (c == EOF) + return TOKEN_ERROR; + + if (c == '(') + return TOKEN_PATTERN_OPEN_PAREN; + else + return TOKEN_ERROR; + } + return TOKEN_ERROR; + + default : + if (isdigit(c) || c == '-') + { + int have_nondigits = 0; + int have_digits = 0; + int have_floating_point = 0; + + do + { + if (isdigit(c)) + have_digits = 1; + else if (c == '.') + have_floating_point++; + _token_append(c); + + c = _next_char(stream); + + if (c != EOF && !isdigit(c) && !isspace(c) && c != '.' && !strchr(delims, c)) + have_nondigits = 1; + } while (c != EOF && !isspace(c) && !strchr(delims, c)); + + if (c != EOF) + _unget_char(c, stream); + + if (have_nondigits || !have_digits || have_floating_point > 1) + return TOKEN_SYMBOL; + else if (have_floating_point == 1) + return TOKEN_REAL; + else + return TOKEN_INTEGER; + } + else + { + if (c == '.') + { + c = _next_char(stream); + if (c != EOF && !isspace(c) && !strchr(delims, c)) + _token_append('.'); + else + { + _unget_char(c, stream); + return TOKEN_DOT; + } + } + do + { + _token_append(c); + c = _next_char(stream); + } while (c != EOF && !isspace(c) && !strchr(delims, c)); + if (c != EOF) + _unget_char(c, stream); + + return TOKEN_SYMBOL; + } + } + + assert(0); + return TOKEN_ERROR; +} + +static lisp_object_t* +lisp_object_alloc (int type) +{ + lisp_object_t *obj = (lisp_object_t*)malloc(sizeof(lisp_object_t)); + + obj->type = type; + + return obj; +} + +lisp_stream_t* +lisp_stream_init_file (lisp_stream_t *stream, FILE *file) +{ + stream->type = LISP_STREAM_FILE; + stream->v.file = file; + + return stream; +} + +lisp_stream_t* +lisp_stream_init_string (lisp_stream_t *stream, char *buf) +{ + stream->type = LISP_STREAM_STRING; + stream->v.string.buf = buf; + stream->v.string.pos = 0; + + return stream; +} + +lisp_stream_t* +lisp_stream_init_any (lisp_stream_t *stream, void *data, + int (*next_char) (void *data), + void (*unget_char) (char c, void *data)) +{ + assert(next_char != 0 && unget_char != 0); + + stream->type = LISP_STREAM_ANY; + stream->v.any.data = data; + stream->v.any.next_char= next_char; + stream->v.any.unget_char = unget_char; + + return stream; +} + +lisp_object_t* +lisp_make_integer (int value) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_INTEGER); + + obj->v.integer = value; + + return obj; +} + +lisp_object_t* +lisp_make_real (float value) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_REAL); + + obj->v.real = value; + + return obj; +} + +lisp_object_t* +lisp_make_symbol (const char *value) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_SYMBOL); + + obj->v.string = strdup(value); + + return obj; +} + +lisp_object_t* +lisp_make_string (const char *value) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_STRING); + + obj->v.string = strdup(value); + + return obj; +} + +lisp_object_t* +lisp_make_cons (lisp_object_t *car, lisp_object_t *cdr) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_CONS); + + obj->v.cons.car = car; + obj->v.cons.cdr = cdr; + + return obj; +} + +lisp_object_t* +lisp_make_boolean (int value) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_BOOLEAN); + + obj->v.integer = value ? 1 : 0; + + return obj; +} + +static lisp_object_t* +lisp_make_pattern_cons (lisp_object_t *car, lisp_object_t *cdr) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_CONS); + + obj->v.cons.car = car; + obj->v.cons.cdr = cdr; + + return obj; +} + +static lisp_object_t* +lisp_make_pattern_var (int type, int index, lisp_object_t *sub) +{ + lisp_object_t *obj = lisp_object_alloc(LISP_TYPE_PATTERN_VAR); + + obj->v.pattern.type = type; + obj->v.pattern.index = index; + obj->v.pattern.sub = sub; + + return obj; +} + +lisp_object_t* +lisp_read (lisp_stream_t *in) +{ + int token = _scan(in); + lisp_object_t *obj = lisp_nil(); + + if (token == TOKEN_EOF) + return &end_marker; + + switch (token) + { + case TOKEN_ERROR : + return &error_object; + + case TOKEN_EOF : + return &end_marker; + + case TOKEN_OPEN_PAREN : + case TOKEN_PATTERN_OPEN_PAREN : + { + lisp_object_t *last = lisp_nil(), *car; + + do + { + car = lisp_read(in); + if (car == &error_object || car == &end_marker) + { + lisp_free(obj); + return &error_object; + } + else if (car == &dot_marker) + { + if (lisp_nil_p(last)) + { + lisp_free(obj); + return &error_object; + } + + car = lisp_read(in); + if (car == &error_object || car == &end_marker) + { + lisp_free(obj); + return car; + } + else + { + last->v.cons.cdr = car; + + if (_scan(in) != TOKEN_CLOSE_PAREN) + { + lisp_free(obj); + return &error_object; + } + + car = &close_paren_marker; + } + } + else if (car != &close_paren_marker) + { + if (lisp_nil_p(last)) + obj = last = (token == TOKEN_OPEN_PAREN ? lisp_make_cons(car, lisp_nil()) : lisp_make_pattern_cons(car, lisp_nil())); + else + last = last->v.cons.cdr = lisp_make_cons(car, lisp_nil()); + } + } while (car != &close_paren_marker); + } + return obj; + + case TOKEN_CLOSE_PAREN : + return &close_paren_marker; + + case TOKEN_SYMBOL : + return lisp_make_symbol(token_string); + + case TOKEN_STRING : + return lisp_make_string(token_string); + + case TOKEN_INTEGER : + return lisp_make_integer(atoi(token_string)); + + case TOKEN_REAL : + return lisp_make_real((float)atof(token_string)); + + case TOKEN_DOT : + return &dot_marker; + + case TOKEN_TRUE : + return lisp_make_boolean(1); + + case TOKEN_FALSE : + return lisp_make_boolean(0); + } + + assert(0); + return &error_object; +} + +void +lisp_free (lisp_object_t *obj) +{ + if (obj == 0) + return; + + switch (obj->type) + { + case LISP_TYPE_INTERNAL : + case LISP_TYPE_PARSE_ERROR : + case LISP_TYPE_EOF : + return; + + case LISP_TYPE_SYMBOL : + case LISP_TYPE_STRING : + free(obj->v.string); + break; + + case LISP_TYPE_CONS : + case LISP_TYPE_PATTERN_CONS : + lisp_free(obj->v.cons.car); + lisp_free(obj->v.cons.cdr); + break; + + case LISP_TYPE_PATTERN_VAR : + lisp_free(obj->v.pattern.sub); + break; + } + + free(obj); +} + +lisp_object_t* +lisp_read_from_string (const char *buf) +{ + lisp_stream_t stream; + + lisp_stream_init_string(&stream, (char*)buf); + return lisp_read(&stream); +} + +static int +_compile_pattern (lisp_object_t **obj, int *index) +{ + if (*obj == 0) + return 1; + + switch (lisp_type(*obj)) + { + case LISP_TYPE_PATTERN_CONS : + { + struct { char *name; int type; } types[] = + { + { "any", LISP_PATTERN_ANY }, + { "symbol", LISP_PATTERN_SYMBOL }, + { "string", LISP_PATTERN_STRING }, + { "integer", LISP_PATTERN_INTEGER }, + { "real", LISP_PATTERN_REAL }, + { "boolean", LISP_PATTERN_BOOLEAN }, + { "list", LISP_PATTERN_LIST }, + { "or", LISP_PATTERN_OR }, + { 0, 0 } + }; + char *type_name; + int type; + int i; + lisp_object_t *pattern; + + if (lisp_type(lisp_car(*obj)) != LISP_TYPE_SYMBOL) + return 0; + + type_name = lisp_symbol(lisp_car(*obj)); + for (i = 0; types[i].name != 0; ++i) + { + if (strcmp(types[i].name, type_name) == 0) + { + type = types[i].type; + break; + } + } + + if (types[i].name == 0) + return 0; + + if (type != LISP_PATTERN_OR && lisp_cdr(*obj) != 0) + return 0; + + pattern = lisp_make_pattern_var(type, (*index)++, lisp_nil()); + + if (type == LISP_PATTERN_OR) + { + lisp_object_t *cdr = lisp_cdr(*obj); + + if (!_compile_pattern(&cdr, index)) + { + lisp_free(pattern); + return 0; + } + + pattern->v.pattern.sub = cdr; + + (*obj)->v.cons.cdr = lisp_nil(); + } + + lisp_free(*obj); + + *obj = pattern; + } + break; + + case LISP_TYPE_CONS : + if (!_compile_pattern(&(*obj)->v.cons.car, index)) + return 0; + if (!_compile_pattern(&(*obj)->v.cons.cdr, index)) + return 0; + break; + } + + return 1; +} + +int +lisp_compile_pattern (lisp_object_t **obj, int *num_subs) +{ + int index = 0; + int result; + + result = _compile_pattern(obj, &index); + + if (result && num_subs != 0) + *num_subs = index; + + return result; +} + +static int _match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars); + +static int +_match_pattern_var (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars) +{ + assert(lisp_type(pattern) == LISP_TYPE_PATTERN_VAR); + + switch (pattern->v.pattern.type) + { + case LISP_PATTERN_ANY : + break; + + case LISP_PATTERN_SYMBOL : + if (obj == 0 || lisp_type(obj) != LISP_TYPE_SYMBOL) + return 0; + break; + + case LISP_PATTERN_STRING : + if (obj == 0 || lisp_type(obj) != LISP_TYPE_STRING) + return 0; + break; + + case LISP_PATTERN_INTEGER : + if (obj == 0 || lisp_type(obj) != LISP_TYPE_INTEGER) + return 0; + break; + + case LISP_PATTERN_REAL : + if (obj == 0 || lisp_type(obj) != LISP_TYPE_REAL) + return 0; + break; + + case LISP_PATTERN_BOOLEAN : + if (obj == 0 || lisp_type(obj) != LISP_TYPE_BOOLEAN) + return 0; + break; + + case LISP_PATTERN_LIST : + if (obj == 0 || lisp_type(obj) != LISP_TYPE_CONS) + return 0; + break; + + case LISP_PATTERN_OR : + { + lisp_object_t *sub; + int matched = 0; + + for (sub = pattern->v.pattern.sub; sub != 0; sub = lisp_cdr(sub)) + { + assert(lisp_type(sub) == LISP_TYPE_CONS); + + if (_match_pattern(lisp_car(sub), obj, vars)) + matched = 1; + } + + if (!matched) + return 0; + } + break; + + default : + assert(0); + } + + if (vars != 0) + vars[pattern->v.pattern.index] = obj; + + return 1; +} + +static int +_match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars) +{ + if (pattern == 0) + return obj == 0; + + if (obj == 0) + return 0; + + if (lisp_type(pattern) == LISP_TYPE_PATTERN_VAR) + return _match_pattern_var(pattern, obj, vars); + + if (lisp_type(pattern) != lisp_type(obj)) + return 0; + + switch (lisp_type(pattern)) + { + case LISP_TYPE_SYMBOL : + return strcmp(lisp_symbol(pattern), lisp_symbol(obj)) == 0; + + case LISP_TYPE_STRING : + return strcmp(lisp_string(pattern), lisp_string(obj)) == 0; + + case LISP_TYPE_INTEGER : + return lisp_integer(pattern) == lisp_integer(obj); + + case LISP_TYPE_REAL : + return lisp_real(pattern) == lisp_real(obj); + + case LISP_TYPE_CONS : + { + int result1, result2; + + result1 = _match_pattern(lisp_car(pattern), lisp_car(obj), vars); + result2 = _match_pattern(lisp_cdr(pattern), lisp_cdr(obj), vars); + + return result1 && result2; + } + break; + + default : + assert(0); + } + + return 0; +} + +int +lisp_match_pattern (lisp_object_t *pattern, lisp_object_t *obj, lisp_object_t **vars, int num_subs) +{ + int i; + + if (vars != 0) + for (i = 0; i < num_subs; ++i) + vars[i] = &error_object; + + return _match_pattern(pattern, obj, vars); +} + +int +lisp_match_string (const char *pattern_string, lisp_object_t *obj, lisp_object_t **vars) +{ + lisp_object_t *pattern; + int result; + int num_subs; + + pattern = lisp_read_from_string(pattern_string); + + if (pattern != 0 && (lisp_type(pattern) == LISP_TYPE_EOF + || lisp_type(pattern) == LISP_TYPE_PARSE_ERROR)) + return 0; + + if (!lisp_compile_pattern(&pattern, &num_subs)) + { + lisp_free(pattern); + return 0; + } + + result = lisp_match_pattern(pattern, obj, vars, num_subs); + + lisp_free(pattern); + + return result; +} + +int +lisp_type (lisp_object_t *obj) +{ + if (obj == 0) + return LISP_TYPE_NIL; + return obj->type; +} + +int +lisp_integer (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_INTEGER); + + return obj->v.integer; +} + +char* +lisp_symbol (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_SYMBOL); + + return obj->v.string; +} + +char* +lisp_string (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_STRING); + + return obj->v.string; +} + +int +lisp_boolean (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_BOOLEAN); + + return obj->v.integer; +} + +float +lisp_real (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_REAL || obj->type == LISP_TYPE_INTEGER); + + if (obj->type == LISP_TYPE_INTEGER) + return obj->v.integer; + return obj->v.real; +} + +lisp_object_t* +lisp_car (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); + + return obj->v.cons.car; +} + +lisp_object_t* +lisp_cdr (lisp_object_t *obj) +{ + assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); + + return obj->v.cons.cdr; +} + +lisp_object_t* +lisp_cxr (lisp_object_t *obj, const char *x) +{ + int i; + + for (i = strlen(x) - 1; i >= 0; --i) + if (x[i] == 'a') + obj = lisp_car(obj); + else if (x[i] == 'd') + obj = lisp_cdr(obj); + else + assert(0); + + return obj; +} + +int +lisp_list_length (lisp_object_t *obj) +{ + int length = 0; + + while (obj != 0) + { + assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); + + ++length; + obj = obj->v.cons.cdr; + } + + return length; +} + +lisp_object_t* +lisp_list_nth_cdr (lisp_object_t *obj, int index) +{ + while (index > 0) + { + assert(obj != 0); + assert(obj->type == LISP_TYPE_CONS || obj->type == LISP_TYPE_PATTERN_CONS); + + --index; + obj = obj->v.cons.cdr; + } + + return obj; +} + +lisp_object_t* +lisp_list_nth (lisp_object_t *obj, int index) +{ + obj = lisp_list_nth_cdr(obj, index); + + assert(obj != 0); + + return obj->v.cons.car; +} + +void +lisp_dump (lisp_object_t *obj, FILE *out) +{ + if (obj == 0) + { + fprintf(out, "()"); + return; + } + + switch (lisp_type(obj)) + { + case LISP_TYPE_EOF : + fputs("#", out); + break; + + case LISP_TYPE_PARSE_ERROR : + fputs("#", out); + break; + + case LISP_TYPE_INTEGER : + fprintf(out, "%d", lisp_integer(obj)); + break; + + case LISP_TYPE_REAL : + fprintf(out, "%f", lisp_real(obj)); + break; + + case LISP_TYPE_SYMBOL : + fputs(lisp_symbol(obj), out); + break; + + case LISP_TYPE_STRING : + { + char *p; + + fputc('"', out); + for (p = lisp_string(obj); *p != 0; ++p) + { + if (*p == '"' || *p == '\\') + fputc('\\', out); + fputc(*p, out); + } + fputc('"', out); + } + break; + + case LISP_TYPE_CONS : + case LISP_TYPE_PATTERN_CONS : + fputs(lisp_type(obj) == LISP_TYPE_CONS ? "(" : "#?(", out); + while (obj != 0) + { + lisp_dump(lisp_car(obj), out); + obj = lisp_cdr(obj); + if (obj != 0) + { + if (lisp_type(obj) != LISP_TYPE_CONS + && lisp_type(obj) != LISP_TYPE_PATTERN_CONS) + { + fputs(" . ", out); + lisp_dump(obj, out); + break; + } + else + fputc(' ', out); + } + } + fputc(')', out); + break; + + case LISP_TYPE_BOOLEAN : + if (lisp_boolean(obj)) + fputs("#t", out); + else + fputs("#f", out); + break; + + default : + assert(0); + } +} diff --git a/src/menu.c b/src/menu.c deleted file mode 100644 index edfb20517..000000000 --- a/src/menu.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - menu.c - - Super Tux - Menu - - by Tobias Glaesser - tobi.web@gmx.de - http://www.newbreedsoftware.com/supertux/ - - December 20, 2003 - March 15, 2004 -*/ - -#ifdef LINUX -#include -#include -#include -#endif - -#include -#include -#include - -#include "defines.h" -#include "globals.h" -#include "menu.h" -#include "screen.h" -#include "setup.h" -#include "sound.h" -#include "scene.h" -#include "leveleditor.h" -#include "timer.h" -#include "high_scores.h" - -/* (global) menu variables */ -int menuaction; -int show_menu; -int menu_change; -texture_type checkbox, checkbox_checked, back, arrow_left, arrow_right; - -menu_type main_menu, game_menu, options_menu, highscore_menu, load_game_menu, save_game_menu; -menu_type* current_menu, * last_menu; - -/* input implementation variables */ -int delete_character; -char mn_input_char; - -/* Set the current menu */ -void menu_set_current(menu_type* pmenu) -{ - if(pmenu != current_menu) - { - menu_change = YES; - last_menu = current_menu; - current_menu = pmenu; - timer_start(&pmenu->effect, 500); - } -} - -/* Return a pointer to a new menu item */ -menu_item_type* menu_item_create(int kind, char *text, int init_toggle, void* target_menu) -{ - menu_item_type *pnew_item = (menu_item_type*) malloc(sizeof(menu_item_type)); - pnew_item->kind = kind; - pnew_item->text = (char*) malloc(sizeof(char) * (strlen(text) + 1)); - strcpy(pnew_item->text,text); - if(kind == MN_TOGGLE) - pnew_item->toggled = init_toggle; - else - pnew_item->toggled = NO; - pnew_item->target_menu = target_menu; - pnew_item->input = (char*) malloc(sizeof(char)); - pnew_item->input[0] = '\0'; - if(kind == MN_STRINGSELECT) - { - pnew_item->list = (string_list_type*) malloc(sizeof(string_list_type)); - string_list_init(pnew_item->list); - } - else - pnew_item->list = NULL; - return pnew_item; -} - -void menu_item_change_text(menu_item_type* pmenu_item, char *text) -{ - if(text) - { - free(pmenu_item->text); - pmenu_item->text = (char*) malloc(sizeof(char )*(strlen(text)+1)); - strcpy(pmenu_item->text,text); - } -} -void menu_item_change_input(menu_item_type* pmenu_item, char *text) -{ - if(text) - { - free(pmenu_item->input); - pmenu_item->input = (char*) malloc(sizeof(char )*(strlen(text)+1)); - strcpy(pmenu_item->input,text); - } -} - -/* Free a menu and all its items */ -void menu_free(menu_type* pmenu) -{ - int i; - if(pmenu->num_items != 0 && pmenu->item != NULL) - { - for(i = 0; i < pmenu->num_items; ++i) - { - free(pmenu->item[i].text); - free(pmenu->item[i].input); - string_list_free(pmenu->item[i].list); - } - free(pmenu->item); - } -} - -/* Initialize a menu */ -void menu_init(menu_type* pmenu) -{ - pmenu->arrange_left = 0; - pmenu->num_items = 0; - pmenu->active_item = 0; - pmenu->item = NULL; - timer_init(&pmenu->effect,NO); -} - -/* Add an item to a menu */ -void menu_additem(menu_type* pmenu, menu_item_type* pmenu_item) -{ - ++pmenu->num_items; - pmenu->item = (menu_item_type*) realloc(pmenu->item, sizeof(menu_item_type) * pmenu->num_items); - memcpy(&pmenu->item[pmenu->num_items-1],pmenu_item,sizeof(menu_item_type)); - free(pmenu_item); -} - -/* Process actions done on the menu */ -void menu_action(menu_type* pmenu) -{ - int i; - - if(pmenu->num_items != 0 && pmenu->item != NULL) - { - switch(menuaction) - { - case MN_UP: - if(pmenu->active_item > 0) - --pmenu->active_item; - else - pmenu->active_item = pmenu->num_items-1; - break; - case MN_DOWN: - if(pmenu->active_item < pmenu->num_items-1) - ++pmenu->active_item; - else - pmenu->active_item = 0; - break; - case MN_LEFT: - if(pmenu->item[pmenu->active_item].kind == MN_STRINGSELECT && pmenu->item[pmenu->active_item].list->num_items != 0) - { - if(pmenu->item[pmenu->active_item].list->active_item > 0) - --pmenu->item[pmenu->active_item].list->active_item; - else - pmenu->item[pmenu->active_item].list->active_item = pmenu->item[pmenu->active_item].list->num_items-1; - } - break; - case MN_RIGHT: - if(pmenu->item[pmenu->active_item].kind == MN_STRINGSELECT && pmenu->item[pmenu->active_item].list->num_items != 0) - { - if(pmenu->item[pmenu->active_item].list->active_item < pmenu->item[pmenu->active_item].list->num_items-1) - ++pmenu->item[pmenu->active_item].list->active_item; - else - pmenu->item[pmenu->active_item].list->active_item = 0; - } - break; - case MN_HIT: - if(pmenu->item[pmenu->active_item].kind == MN_GOTO && pmenu->item[pmenu->active_item].target_menu != NULL) - menu_set_current((menu_type*)pmenu->item[pmenu->active_item].target_menu); - else if(pmenu->item[pmenu->active_item].kind == MN_TOGGLE) - { - pmenu->item[pmenu->active_item].toggled = !pmenu->item[pmenu->active_item].toggled; - menu_change = YES; - } - else if(pmenu->item[pmenu->active_item].kind == MN_ACTION || pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || pmenu->item[pmenu->active_item].kind == MN_NUMFIELD) - { - pmenu->item[pmenu->active_item].toggled = YES; - } - else if(pmenu->item[pmenu->active_item].kind == MN_BACK) - { - if(last_menu != NULL) - menu_set_current(last_menu); - } - break; - case MN_REMOVE: - if(pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || pmenu->item[pmenu->active_item].kind == MN_NUMFIELD) - { - if(pmenu->item[pmenu->active_item].input != NULL) - { - i = strlen(pmenu->item[pmenu->active_item].input); - - while(delete_character > 0) /* remove charactes */ - { - pmenu->item[pmenu->active_item].input[i-1] = '\0'; - delete_character--; - } - } - } - break; - case MN_INPUT: - if(pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || (pmenu->item[pmenu->active_item].kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) - { - if(pmenu->item[pmenu->active_item].input != NULL) - { - i = strlen(pmenu->item[pmenu->active_item].input); - pmenu->item[pmenu->active_item].input = (char*) realloc(pmenu->item[pmenu->active_item].input,sizeof(char)*(i + 2)); - pmenu->item[pmenu->active_item].input[i] = mn_input_char; - pmenu->item[pmenu->active_item].input[i+1] = '\0'; - } - else - { - pmenu->item[pmenu->active_item].input = (char*) malloc(2*sizeof(char)); - pmenu->item[pmenu->active_item].input[0] = mn_input_char; - pmenu->item[pmenu->active_item].input[1] = '\0'; - } - } - break; - } - } - - if(pmenu->item[pmenu->active_item].kind == MN_DEACTIVE || pmenu->item[pmenu->active_item].kind == MN_LABEL || pmenu->item[pmenu->active_item].kind == MN_HL) - { - if(menuaction != MN_UP && menuaction != MN_DOWN) - menuaction = MN_DOWN; - - if(pmenu->num_items > 1) - menu_action(pmenu); - } - -} - -/* Check, if the value of the active menu item has changed. */ -int menu_check(menu_type* pmenu) -{ - if(pmenu->num_items != 0 && pmenu->item != NULL) - { - if((pmenu->item[pmenu->active_item].kind == MN_ACTION || pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || pmenu->item[pmenu->active_item].kind == MN_NUMFIELD) && pmenu->item[pmenu->active_item].toggled == YES) - { - pmenu->item[pmenu->active_item].toggled = NO; - show_menu = 0; - return pmenu->active_item; - } - else if(pmenu->item[pmenu->active_item].kind == MN_TOGGLE || pmenu->item[pmenu->active_item].kind == MN_GOTO) - { - return pmenu->active_item; - } - else - return -1; - } - else - return -1; -} - -/* Draw the current menu. */ -void menu_draw(menu_type* pmenu) -{ - int i, y, a, b, e, f, menu_height, menu_width; - - /* The width of the menu has to be more than the width of the text with the most characters */ - menu_width = 0; - for(i = 0; i < pmenu->num_items; ++i) - { - y = strlen(pmenu->item[i].text) + (pmenu->item[i].input ? strlen(pmenu->item[i].input) + 1 : 0) + strlen(string_list_active(pmenu->item[i].list)); - if( y > menu_width ) - { - menu_width = y; - if( pmenu->item[i].kind == MN_TOGGLE) - menu_width += 2; - } - } - if(pmenu->arrange_left == YES) - a = menu_width * 16; - else - a = 0; - - menu_width = menu_width * 16 + 48; - menu_height = (pmenu->num_items) * 24; - - /* Draw a transparent background */ - fillrect(screen->w/2 - menu_width/2,screen->h/2-(((pmenu->num_items)*24)/2),menu_width,menu_height,150,150,150,100); - - if(timer_check(&pmenu->effect)) - { - e = timer_get_left(&pmenu->effect) / 4; - } - else - { - e = 0; - } - - for(i = 0; i < pmenu->num_items; ++i) - { - if(pmenu->arrange_left == YES) - b = (a - ((strlen(pmenu->item[i].text)+strlen(pmenu->item[i].input)+ strlen(string_list_active(pmenu->item[i].list))) * 16)) / 2; - else - b = 0; - - if(e != 0) - { - if(i % 2) - f = e; - else - f = -e; - } - else - f = 0; - - if(pmenu->item[i].kind == MN_DEACTIVE) - { - text_drawf(&black_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - } - else if(pmenu->item[i].kind == MN_HL) - { - /* Draw a horizontal line with a little 3d effect */ - fillrect(screen->w/2 - menu_width/2,(i)*24 - menu_height/2 + 6 + screen->h /2,menu_width,4,210,50,50,225); - fillrect(screen->w/2 - menu_width/2,(i)*24 - menu_height/2 + 10 + screen->h /2,menu_width,2,0,0,0,255); - } - else if(pmenu->item[i].kind == MN_LABEL) - { - text_drawf(&white_big_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - } - else if(pmenu->item[i].kind == MN_TEXTFIELD || pmenu->item[i].kind == MN_NUMFIELD) - { - fillrect(-b +screen->w/2 - ((strlen(pmenu->item[i].input)*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 1,(i)*24 - menu_height/2 + 10 + screen->h /2 - 10 + f,(strlen(pmenu->item[i].input)+1)*16 + 2,20,255,255,255,255); - fillrect(- b +screen->w/2 - ((strlen(pmenu->item[i].input)*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2,(i)*24 - menu_height/2 + 10 + screen->h /2 - 9 + f,(strlen(pmenu->item[i].input)+1)*16,18,0,0,0,128); - text_drawf(&gold_text,pmenu->item[i].input, - b + ((strlen(pmenu->item[i].text)+1) * 16)/2,(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - if(i == pmenu->active_item) - { - text_drawf(&blue_text,pmenu->item[i].text, - b -(((strlen(pmenu->item[i].input)+1) * 16)/2),(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,3,NO_UPDATE); - } - else - { - text_drawf(&white_text,pmenu->item[i].text, - b -(((strlen(pmenu->item[i].input)+1) * 16)/2),(i)*24 - menu_height/2 +10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - } - } - else if(pmenu->item[i].kind == MN_STRINGSELECT) - { - /* Draw arrows */ - texture_draw(&arrow_left,-b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 17,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); - texture_draw(&arrow_right,-b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 1 + (strlen(string_list_active(pmenu->item[i].list))+1)*16,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); - /* Draw input background */ - fillrect(-b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 1,(i)*24 - menu_height/2 + 10 + screen->h /2 - 10 + f,(strlen(string_list_active(pmenu->item[i].list))+1)*16 + 2,20,255,255,255,255); - fillrect(- b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2,(i)*24 - menu_height/2 + 10 + screen->h /2 - 9 + f,(strlen(string_list_active(pmenu->item[i].list))+1)*16,18,0,0,0,128); - - text_drawf(&gold_text,string_list_active(pmenu->item[i].list), - b + ((strlen(pmenu->item[i].text)+1) * 16)/2,(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - if(i == pmenu->active_item) - { - text_drawf(&blue_text,pmenu->item[i].text, - b -(((strlen(string_list_active(pmenu->item[i].list))+1) * 16)/2),(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,3,NO_UPDATE); - } - else - { - text_drawf(&white_text,pmenu->item[i].text, - b -(((strlen(string_list_active(pmenu->item[i].list))+1) * 16)/2),(i)*24 - menu_height/2 +10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - } - } - else if(i == pmenu->active_item) - { - text_drawf(&blue_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10 + f ,A_HMIDDLE, A_VMIDDLE,3,NO_UPDATE); - } - else - { - text_drawf(&white_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10 + f ,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); - } - if(pmenu->item[i].kind == MN_TOGGLE) - { - - if(pmenu->item[i].toggled == YES) - texture_draw(&checkbox_checked, - b + screen->w / 2 + (strlen(pmenu->item[i].text) * 16)/2 + 16,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); - else - texture_draw(&checkbox, - b + screen->w / 2 + (strlen(pmenu->item[i].text) * 16)/2 + 16,(i)*24 - menu_height/2 + 10 + screen->h / 2 - 8 + f,NO_UPDATE); - } - else if(pmenu->item[i].kind == MN_BACK) - { - texture_draw(&back, - b + screen->w / 2 + (strlen(pmenu->item[i].text) * 16)/2 + 16,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); - } - } -} - -/* Reset/Set global defaults */ -void menu_reset(void) -{ - menu_change = NO; - show_menu = NO; - menuaction = -1; - current_menu = NULL; - last_menu = NULL; - - delete_character = 0; - mn_input_char = '\0'; -} - -/* --- MENU --- */ -/* Draw the current menu and execute the (menu)events */ -void menu_process_current(void) -{ - menu_change = NO; - - if(current_menu != NULL) - { - menu_action(current_menu); - menu_draw(current_menu); - } - - menuaction = -1; -} - -/* Check for menu event */ -void menu_event(SDL_keysym* keysym) -{ - SDLKey key = keysym->sym; - SDLMod keymod; - char ch[2]; - keymod = SDL_GetModState(); - - /* If the current unicode character is an ASCII character, - assign it to ch. */ - if ( (keysym->unicode & 0xFF80) == 0 ) - { - ch[0] = keysym->unicode & 0x7F; - ch[1] = '\0'; - } - else - { - /* An International Character. */ - } - - switch(key) - { - case SDLK_UP: /* Menu Up */ - menuaction = MN_UP; - menu_change = YES; - break; - case SDLK_DOWN: /* Menu Down */ - menuaction = MN_DOWN; - menu_change = YES; - break; - case SDLK_LEFT: /* Menu Up */ - menuaction = MN_LEFT; - menu_change = YES; - break; - case SDLK_RIGHT: /* Menu Down */ - menuaction = MN_RIGHT; - menu_change = YES; - break; - case SDLK_SPACE: - if(current_menu->item[current_menu->active_item].kind == MN_TEXTFIELD) - { - menuaction = MN_INPUT; - menu_change = YES; - mn_input_char = ' '; - break; - } - case SDLK_RETURN: /* Menu Hit */ - menuaction = MN_HIT; - menu_change = YES; - break; - case SDLK_DELETE: - case SDLK_BACKSPACE: - menuaction = MN_REMOVE; - menu_change = YES; - delete_character++; - break; - default: - if( (key >= SDLK_0 && key <= SDLK_9) || (key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_SPACE && key <= SDLK_SLASH)) - { - menuaction = MN_INPUT; - menu_change = YES; - mn_input_char = *ch; - } - else - { - mn_input_char = '\0'; - } - break; - } - - - /* FIXME: NO JOYSTICK SUPPORT */ - /*#ifdef JOY_YES - else if (event.type == SDL_JOYBUTTONDOWN) - { - Joystick button: Continue: - - done = 1; - } - #endif*/ -} - diff --git a/src/menu.cpp b/src/menu.cpp new file mode 100644 index 000000000..edfb20517 --- /dev/null +++ b/src/menu.cpp @@ -0,0 +1,496 @@ +/* + menu.c + + Super Tux - Menu + + by Tobias Glaesser + tobi.web@gmx.de + http://www.newbreedsoftware.com/supertux/ + + December 20, 2003 - March 15, 2004 +*/ + +#ifdef LINUX +#include +#include +#include +#endif + +#include +#include +#include + +#include "defines.h" +#include "globals.h" +#include "menu.h" +#include "screen.h" +#include "setup.h" +#include "sound.h" +#include "scene.h" +#include "leveleditor.h" +#include "timer.h" +#include "high_scores.h" + +/* (global) menu variables */ +int menuaction; +int show_menu; +int menu_change; +texture_type checkbox, checkbox_checked, back, arrow_left, arrow_right; + +menu_type main_menu, game_menu, options_menu, highscore_menu, load_game_menu, save_game_menu; +menu_type* current_menu, * last_menu; + +/* input implementation variables */ +int delete_character; +char mn_input_char; + +/* Set the current menu */ +void menu_set_current(menu_type* pmenu) +{ + if(pmenu != current_menu) + { + menu_change = YES; + last_menu = current_menu; + current_menu = pmenu; + timer_start(&pmenu->effect, 500); + } +} + +/* Return a pointer to a new menu item */ +menu_item_type* menu_item_create(int kind, char *text, int init_toggle, void* target_menu) +{ + menu_item_type *pnew_item = (menu_item_type*) malloc(sizeof(menu_item_type)); + pnew_item->kind = kind; + pnew_item->text = (char*) malloc(sizeof(char) * (strlen(text) + 1)); + strcpy(pnew_item->text,text); + if(kind == MN_TOGGLE) + pnew_item->toggled = init_toggle; + else + pnew_item->toggled = NO; + pnew_item->target_menu = target_menu; + pnew_item->input = (char*) malloc(sizeof(char)); + pnew_item->input[0] = '\0'; + if(kind == MN_STRINGSELECT) + { + pnew_item->list = (string_list_type*) malloc(sizeof(string_list_type)); + string_list_init(pnew_item->list); + } + else + pnew_item->list = NULL; + return pnew_item; +} + +void menu_item_change_text(menu_item_type* pmenu_item, char *text) +{ + if(text) + { + free(pmenu_item->text); + pmenu_item->text = (char*) malloc(sizeof(char )*(strlen(text)+1)); + strcpy(pmenu_item->text,text); + } +} +void menu_item_change_input(menu_item_type* pmenu_item, char *text) +{ + if(text) + { + free(pmenu_item->input); + pmenu_item->input = (char*) malloc(sizeof(char )*(strlen(text)+1)); + strcpy(pmenu_item->input,text); + } +} + +/* Free a menu and all its items */ +void menu_free(menu_type* pmenu) +{ + int i; + if(pmenu->num_items != 0 && pmenu->item != NULL) + { + for(i = 0; i < pmenu->num_items; ++i) + { + free(pmenu->item[i].text); + free(pmenu->item[i].input); + string_list_free(pmenu->item[i].list); + } + free(pmenu->item); + } +} + +/* Initialize a menu */ +void menu_init(menu_type* pmenu) +{ + pmenu->arrange_left = 0; + pmenu->num_items = 0; + pmenu->active_item = 0; + pmenu->item = NULL; + timer_init(&pmenu->effect,NO); +} + +/* Add an item to a menu */ +void menu_additem(menu_type* pmenu, menu_item_type* pmenu_item) +{ + ++pmenu->num_items; + pmenu->item = (menu_item_type*) realloc(pmenu->item, sizeof(menu_item_type) * pmenu->num_items); + memcpy(&pmenu->item[pmenu->num_items-1],pmenu_item,sizeof(menu_item_type)); + free(pmenu_item); +} + +/* Process actions done on the menu */ +void menu_action(menu_type* pmenu) +{ + int i; + + if(pmenu->num_items != 0 && pmenu->item != NULL) + { + switch(menuaction) + { + case MN_UP: + if(pmenu->active_item > 0) + --pmenu->active_item; + else + pmenu->active_item = pmenu->num_items-1; + break; + case MN_DOWN: + if(pmenu->active_item < pmenu->num_items-1) + ++pmenu->active_item; + else + pmenu->active_item = 0; + break; + case MN_LEFT: + if(pmenu->item[pmenu->active_item].kind == MN_STRINGSELECT && pmenu->item[pmenu->active_item].list->num_items != 0) + { + if(pmenu->item[pmenu->active_item].list->active_item > 0) + --pmenu->item[pmenu->active_item].list->active_item; + else + pmenu->item[pmenu->active_item].list->active_item = pmenu->item[pmenu->active_item].list->num_items-1; + } + break; + case MN_RIGHT: + if(pmenu->item[pmenu->active_item].kind == MN_STRINGSELECT && pmenu->item[pmenu->active_item].list->num_items != 0) + { + if(pmenu->item[pmenu->active_item].list->active_item < pmenu->item[pmenu->active_item].list->num_items-1) + ++pmenu->item[pmenu->active_item].list->active_item; + else + pmenu->item[pmenu->active_item].list->active_item = 0; + } + break; + case MN_HIT: + if(pmenu->item[pmenu->active_item].kind == MN_GOTO && pmenu->item[pmenu->active_item].target_menu != NULL) + menu_set_current((menu_type*)pmenu->item[pmenu->active_item].target_menu); + else if(pmenu->item[pmenu->active_item].kind == MN_TOGGLE) + { + pmenu->item[pmenu->active_item].toggled = !pmenu->item[pmenu->active_item].toggled; + menu_change = YES; + } + else if(pmenu->item[pmenu->active_item].kind == MN_ACTION || pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || pmenu->item[pmenu->active_item].kind == MN_NUMFIELD) + { + pmenu->item[pmenu->active_item].toggled = YES; + } + else if(pmenu->item[pmenu->active_item].kind == MN_BACK) + { + if(last_menu != NULL) + menu_set_current(last_menu); + } + break; + case MN_REMOVE: + if(pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || pmenu->item[pmenu->active_item].kind == MN_NUMFIELD) + { + if(pmenu->item[pmenu->active_item].input != NULL) + { + i = strlen(pmenu->item[pmenu->active_item].input); + + while(delete_character > 0) /* remove charactes */ + { + pmenu->item[pmenu->active_item].input[i-1] = '\0'; + delete_character--; + } + } + } + break; + case MN_INPUT: + if(pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || (pmenu->item[pmenu->active_item].kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) + { + if(pmenu->item[pmenu->active_item].input != NULL) + { + i = strlen(pmenu->item[pmenu->active_item].input); + pmenu->item[pmenu->active_item].input = (char*) realloc(pmenu->item[pmenu->active_item].input,sizeof(char)*(i + 2)); + pmenu->item[pmenu->active_item].input[i] = mn_input_char; + pmenu->item[pmenu->active_item].input[i+1] = '\0'; + } + else + { + pmenu->item[pmenu->active_item].input = (char*) malloc(2*sizeof(char)); + pmenu->item[pmenu->active_item].input[0] = mn_input_char; + pmenu->item[pmenu->active_item].input[1] = '\0'; + } + } + break; + } + } + + if(pmenu->item[pmenu->active_item].kind == MN_DEACTIVE || pmenu->item[pmenu->active_item].kind == MN_LABEL || pmenu->item[pmenu->active_item].kind == MN_HL) + { + if(menuaction != MN_UP && menuaction != MN_DOWN) + menuaction = MN_DOWN; + + if(pmenu->num_items > 1) + menu_action(pmenu); + } + +} + +/* Check, if the value of the active menu item has changed. */ +int menu_check(menu_type* pmenu) +{ + if(pmenu->num_items != 0 && pmenu->item != NULL) + { + if((pmenu->item[pmenu->active_item].kind == MN_ACTION || pmenu->item[pmenu->active_item].kind == MN_TEXTFIELD || pmenu->item[pmenu->active_item].kind == MN_NUMFIELD) && pmenu->item[pmenu->active_item].toggled == YES) + { + pmenu->item[pmenu->active_item].toggled = NO; + show_menu = 0; + return pmenu->active_item; + } + else if(pmenu->item[pmenu->active_item].kind == MN_TOGGLE || pmenu->item[pmenu->active_item].kind == MN_GOTO) + { + return pmenu->active_item; + } + else + return -1; + } + else + return -1; +} + +/* Draw the current menu. */ +void menu_draw(menu_type* pmenu) +{ + int i, y, a, b, e, f, menu_height, menu_width; + + /* The width of the menu has to be more than the width of the text with the most characters */ + menu_width = 0; + for(i = 0; i < pmenu->num_items; ++i) + { + y = strlen(pmenu->item[i].text) + (pmenu->item[i].input ? strlen(pmenu->item[i].input) + 1 : 0) + strlen(string_list_active(pmenu->item[i].list)); + if( y > menu_width ) + { + menu_width = y; + if( pmenu->item[i].kind == MN_TOGGLE) + menu_width += 2; + } + } + if(pmenu->arrange_left == YES) + a = menu_width * 16; + else + a = 0; + + menu_width = menu_width * 16 + 48; + menu_height = (pmenu->num_items) * 24; + + /* Draw a transparent background */ + fillrect(screen->w/2 - menu_width/2,screen->h/2-(((pmenu->num_items)*24)/2),menu_width,menu_height,150,150,150,100); + + if(timer_check(&pmenu->effect)) + { + e = timer_get_left(&pmenu->effect) / 4; + } + else + { + e = 0; + } + + for(i = 0; i < pmenu->num_items; ++i) + { + if(pmenu->arrange_left == YES) + b = (a - ((strlen(pmenu->item[i].text)+strlen(pmenu->item[i].input)+ strlen(string_list_active(pmenu->item[i].list))) * 16)) / 2; + else + b = 0; + + if(e != 0) + { + if(i % 2) + f = e; + else + f = -e; + } + else + f = 0; + + if(pmenu->item[i].kind == MN_DEACTIVE) + { + text_drawf(&black_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + } + else if(pmenu->item[i].kind == MN_HL) + { + /* Draw a horizontal line with a little 3d effect */ + fillrect(screen->w/2 - menu_width/2,(i)*24 - menu_height/2 + 6 + screen->h /2,menu_width,4,210,50,50,225); + fillrect(screen->w/2 - menu_width/2,(i)*24 - menu_height/2 + 10 + screen->h /2,menu_width,2,0,0,0,255); + } + else if(pmenu->item[i].kind == MN_LABEL) + { + text_drawf(&white_big_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + } + else if(pmenu->item[i].kind == MN_TEXTFIELD || pmenu->item[i].kind == MN_NUMFIELD) + { + fillrect(-b +screen->w/2 - ((strlen(pmenu->item[i].input)*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 1,(i)*24 - menu_height/2 + 10 + screen->h /2 - 10 + f,(strlen(pmenu->item[i].input)+1)*16 + 2,20,255,255,255,255); + fillrect(- b +screen->w/2 - ((strlen(pmenu->item[i].input)*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2,(i)*24 - menu_height/2 + 10 + screen->h /2 - 9 + f,(strlen(pmenu->item[i].input)+1)*16,18,0,0,0,128); + text_drawf(&gold_text,pmenu->item[i].input, - b + ((strlen(pmenu->item[i].text)+1) * 16)/2,(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + if(i == pmenu->active_item) + { + text_drawf(&blue_text,pmenu->item[i].text, - b -(((strlen(pmenu->item[i].input)+1) * 16)/2),(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,3,NO_UPDATE); + } + else + { + text_drawf(&white_text,pmenu->item[i].text, - b -(((strlen(pmenu->item[i].input)+1) * 16)/2),(i)*24 - menu_height/2 +10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + } + } + else if(pmenu->item[i].kind == MN_STRINGSELECT) + { + /* Draw arrows */ + texture_draw(&arrow_left,-b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 17,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); + texture_draw(&arrow_right,-b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 1 + (strlen(string_list_active(pmenu->item[i].list))+1)*16,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); + /* Draw input background */ + fillrect(-b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2 - 1,(i)*24 - menu_height/2 + 10 + screen->h /2 - 10 + f,(strlen(string_list_active(pmenu->item[i].list))+1)*16 + 2,20,255,255,255,255); + fillrect(- b +screen->w/2 - ((strlen(string_list_active(pmenu->item[i].list))*16)/2) + ((strlen(pmenu->item[i].text) + 1)*16)/2,(i)*24 - menu_height/2 + 10 + screen->h /2 - 9 + f,(strlen(string_list_active(pmenu->item[i].list))+1)*16,18,0,0,0,128); + + text_drawf(&gold_text,string_list_active(pmenu->item[i].list), - b + ((strlen(pmenu->item[i].text)+1) * 16)/2,(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + if(i == pmenu->active_item) + { + text_drawf(&blue_text,pmenu->item[i].text, - b -(((strlen(string_list_active(pmenu->item[i].list))+1) * 16)/2),(i)*24 - menu_height/2 + 10 + f,A_HMIDDLE, A_VMIDDLE,3,NO_UPDATE); + } + else + { + text_drawf(&white_text,pmenu->item[i].text, - b -(((strlen(string_list_active(pmenu->item[i].list))+1) * 16)/2),(i)*24 - menu_height/2 +10 + f,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + } + } + else if(i == pmenu->active_item) + { + text_drawf(&blue_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10 + f ,A_HMIDDLE, A_VMIDDLE,3,NO_UPDATE); + } + else + { + text_drawf(&white_text,pmenu->item[i].text, - b,(i)*24 - menu_height/2 + 10 + f ,A_HMIDDLE, A_VMIDDLE,2,NO_UPDATE); + } + if(pmenu->item[i].kind == MN_TOGGLE) + { + + if(pmenu->item[i].toggled == YES) + texture_draw(&checkbox_checked, - b + screen->w / 2 + (strlen(pmenu->item[i].text) * 16)/2 + 16,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); + else + texture_draw(&checkbox, - b + screen->w / 2 + (strlen(pmenu->item[i].text) * 16)/2 + 16,(i)*24 - menu_height/2 + 10 + screen->h / 2 - 8 + f,NO_UPDATE); + } + else if(pmenu->item[i].kind == MN_BACK) + { + texture_draw(&back, - b + screen->w / 2 + (strlen(pmenu->item[i].text) * 16)/2 + 16,(i)*24 - menu_height/2 + 10 + screen->h / 2 -8 + f,NO_UPDATE); + } + } +} + +/* Reset/Set global defaults */ +void menu_reset(void) +{ + menu_change = NO; + show_menu = NO; + menuaction = -1; + current_menu = NULL; + last_menu = NULL; + + delete_character = 0; + mn_input_char = '\0'; +} + +/* --- MENU --- */ +/* Draw the current menu and execute the (menu)events */ +void menu_process_current(void) +{ + menu_change = NO; + + if(current_menu != NULL) + { + menu_action(current_menu); + menu_draw(current_menu); + } + + menuaction = -1; +} + +/* Check for menu event */ +void menu_event(SDL_keysym* keysym) +{ + SDLKey key = keysym->sym; + SDLMod keymod; + char ch[2]; + keymod = SDL_GetModState(); + + /* If the current unicode character is an ASCII character, + assign it to ch. */ + if ( (keysym->unicode & 0xFF80) == 0 ) + { + ch[0] = keysym->unicode & 0x7F; + ch[1] = '\0'; + } + else + { + /* An International Character. */ + } + + switch(key) + { + case SDLK_UP: /* Menu Up */ + menuaction = MN_UP; + menu_change = YES; + break; + case SDLK_DOWN: /* Menu Down */ + menuaction = MN_DOWN; + menu_change = YES; + break; + case SDLK_LEFT: /* Menu Up */ + menuaction = MN_LEFT; + menu_change = YES; + break; + case SDLK_RIGHT: /* Menu Down */ + menuaction = MN_RIGHT; + menu_change = YES; + break; + case SDLK_SPACE: + if(current_menu->item[current_menu->active_item].kind == MN_TEXTFIELD) + { + menuaction = MN_INPUT; + menu_change = YES; + mn_input_char = ' '; + break; + } + case SDLK_RETURN: /* Menu Hit */ + menuaction = MN_HIT; + menu_change = YES; + break; + case SDLK_DELETE: + case SDLK_BACKSPACE: + menuaction = MN_REMOVE; + menu_change = YES; + delete_character++; + break; + default: + if( (key >= SDLK_0 && key <= SDLK_9) || (key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_SPACE && key <= SDLK_SLASH)) + { + menuaction = MN_INPUT; + menu_change = YES; + mn_input_char = *ch; + } + else + { + mn_input_char = '\0'; + } + break; + } + + + /* FIXME: NO JOYSTICK SUPPORT */ + /*#ifdef JOY_YES + else if (event.type == SDL_JOYBUTTONDOWN) + { + Joystick button: Continue: + + done = 1; + } + #endif*/ +} + diff --git a/src/physic.c b/src/physic.c deleted file mode 100644 index f95c923d7..000000000 --- a/src/physic.c +++ /dev/null @@ -1,84 +0,0 @@ -// -// C Implementation: physic -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include -#include "defines.h" -#include "physic.h" - -float gravity; - -void physic_init(physic_type* pphysic) -{ - pphysic->state = -1; - pphysic->start_time = 0; - pphysic->start_vy = 0; -} - -int physic_get_state(physic_type* pphysic) -{ - return pphysic->state; -} - -void physic_set_state(physic_type* pphysic, int nstate) -{ - pphysic->state = nstate; - pphysic->start_time = st_get_ticks(); -} - -void physic_set_start_vy(physic_type* pphysic, float start_vy) -{ - pphysic->start_vy = start_vy; -} - -void physic_set_start_vx(physic_type* pphysic, float start_vx) -{ - pphysic->start_vx = start_vx; -} - -void physic_set_acceleration(physic_type* pphysic, float acceleration) -{ - pphysic->acceleration = acceleration; -} - - -int physic_is_set(physic_type* pphysic) -{ - if(pphysic->state != -1) - return YES; - else - return NO; -} - -float physic_get_velocity(physic_type* pphysic) -{ - if(pphysic->state == PH_VT) - return - (pphysic->start_vy - gravity* ((float)(st_get_ticks() - pphysic->start_time))/1000.); - else if(pphysic->state == PH_HA) - return - (pphysic->start_vx - pphysic->acceleration * ((float)(st_get_ticks() - pphysic->start_time))/1000.); -} - -float physic_get_max_distance(physic_type* pphysic) -{ - return (pphysic->start_vy * pphysic->start_vy / 2.*gravity); -} - -unsigned int physic_get_max_time(physic_type* pphysic) -{ - return (unsigned int)((pphysic->start_vy / gravity) * 1000); -} - -unsigned int physic_get_time_gone(physic_type* pphysic) -{ - return st_get_ticks() - pphysic->start_time; -} - - diff --git a/src/physic.cpp b/src/physic.cpp new file mode 100644 index 000000000..f95c923d7 --- /dev/null +++ b/src/physic.cpp @@ -0,0 +1,84 @@ +// +// C Implementation: physic +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include "defines.h" +#include "physic.h" + +float gravity; + +void physic_init(physic_type* pphysic) +{ + pphysic->state = -1; + pphysic->start_time = 0; + pphysic->start_vy = 0; +} + +int physic_get_state(physic_type* pphysic) +{ + return pphysic->state; +} + +void physic_set_state(physic_type* pphysic, int nstate) +{ + pphysic->state = nstate; + pphysic->start_time = st_get_ticks(); +} + +void physic_set_start_vy(physic_type* pphysic, float start_vy) +{ + pphysic->start_vy = start_vy; +} + +void physic_set_start_vx(physic_type* pphysic, float start_vx) +{ + pphysic->start_vx = start_vx; +} + +void physic_set_acceleration(physic_type* pphysic, float acceleration) +{ + pphysic->acceleration = acceleration; +} + + +int physic_is_set(physic_type* pphysic) +{ + if(pphysic->state != -1) + return YES; + else + return NO; +} + +float physic_get_velocity(physic_type* pphysic) +{ + if(pphysic->state == PH_VT) + return - (pphysic->start_vy - gravity* ((float)(st_get_ticks() - pphysic->start_time))/1000.); + else if(pphysic->state == PH_HA) + return - (pphysic->start_vx - pphysic->acceleration * ((float)(st_get_ticks() - pphysic->start_time))/1000.); +} + +float physic_get_max_distance(physic_type* pphysic) +{ + return (pphysic->start_vy * pphysic->start_vy / 2.*gravity); +} + +unsigned int physic_get_max_time(physic_type* pphysic) +{ + return (unsigned int)((pphysic->start_vy / gravity) * 1000); +} + +unsigned int physic_get_time_gone(physic_type* pphysic) +{ + return st_get_ticks() - pphysic->start_time; +} + + diff --git a/src/player.c b/src/player.c deleted file mode 100644 index 1f876f3f5..000000000 --- a/src/player.c +++ /dev/null @@ -1,1024 +0,0 @@ -// -// C Implementation: player/tux -// -// Description: -// -// -// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "gameloop.h" -#include "globals.h" -#include "player.h" -#include "defines.h" -#include "scene.h" -#include "screen.h" - -texture_type tux_life, -tux_right[3], tux_left[3], -bigtux_right[3], bigtux_left[3], -bigtux_right_jump, bigtux_left_jump, -ducktux_right, ducktux_left, -skidtux_right, skidtux_left, -firetux_right[3], firetux_left[3], -bigfiretux_right[3], bigfiretux_left[3], -bigfiretux_right_jump, bigfiretux_left_jump, -duckfiretux_right, duckfiretux_left, -skidfiretux_right, skidfiretux_left, -cape_right[2], cape_left[2], -bigcape_right[2], bigcape_left[2]; - -void player_input_init(player_input_type* pplayer_input) -{ - pplayer_input->down = UP; - pplayer_input->fire = UP; - pplayer_input->left = UP; - pplayer_input->old_fire = UP; - pplayer_input->right = UP; - pplayer_input->up = UP; -} - -void player_init(player_type* pplayer) -{ - pplayer->base.width = 32; - pplayer->base.height = 32; - - pplayer->size = SMALL; - pplayer->got_coffee = NO; - - pplayer->base.x = 0; - pplayer->base.y = 240; - pplayer->base.xm = 0; - pplayer->base.ym = 0; - pplayer->old_base = pplayer->base; - pplayer->dir = RIGHT; - pplayer->duck = NO; - - pplayer->dying = NO; - pplayer->jumping = NO; - - pplayer->frame_main = 0; - pplayer->frame = 0; - pplayer->lives = 3; - pplayer->score = 0; - pplayer->distros = 0; - - player_input_init(&pplayer->input); - - pplayer->keymap.jump = SDLK_UP; - pplayer->keymap.duck = SDLK_DOWN; - pplayer->keymap.left = SDLK_LEFT; - pplayer->keymap.right = SDLK_RIGHT; - pplayer->keymap.fire = SDLK_LCTRL; - - timer_init(&pplayer->invincible_timer,YES); - timer_init(&pplayer->skidding_timer,YES); - timer_init(&pplayer->safe_timer,YES); - timer_init(&pplayer->frame_timer,YES); - physic_init(&pplayer->hphysic); - physic_init(&pplayer->vphysic); -} - -int player_key_event(player_type* pplayer, SDLKey key, int state) -{ - if(key == pplayer->keymap.right) - { - pplayer->input.right = state; - return YES; - } - else if( key == pplayer->keymap.left) - { - pplayer->input.left = state; - return YES; - } - else if(key == pplayer->keymap.jump) - { - pplayer->input.up = state; - return YES; - } - else if(key == pplayer->keymap.duck) - { - pplayer->input.down = state; - return YES; - } - else if(key == pplayer->keymap.fire) - { - pplayer->input.fire = state; - return YES; - } - else - return NO; -} - -void player_level_begin(player_type* pplayer) -{ - pplayer->base.x = 0; - pplayer->base.y = 240; - pplayer->base.xm = 0; - pplayer->base.ym = 0; - pplayer->old_base = pplayer->base; - - player_input_init(&pplayer->input); - - timer_init(&pplayer->invincible_timer,YES); - timer_init(&pplayer->skidding_timer,YES); - timer_init(&pplayer->safe_timer,YES); - timer_init(&pplayer->frame_timer,YES); - physic_init(&pplayer->hphysic); - physic_init(&pplayer->vphysic); -} - -void player_action(player_type* pplayer) -{ - int i, jumped_in_solid; - jumped_in_solid = NO; - - /* --- HANDLE TUX! --- */ - - player_input(pplayer); - - /* Move tux: */ - - pplayer->previous_base = pplayer->base; - - pplayer->base.x += pplayer->base.xm * frame_ratio; - pplayer->base.y += pplayer->base.ym * frame_ratio; - - collision_swept_object_map(&pplayer->old_base,&pplayer->base); - - player_keep_in_bounds(pplayer); - - /* Land: */ - - if (!pplayer->dying) - { - - - if( !player_on_ground(pplayer)) - { - if(player_under_solid(pplayer)) - { - physic_set_state(&pplayer->vphysic,PH_VT); - physic_set_start_vy(&pplayer->vphysic,0); - jumped_in_solid = YES; - } - else - { - if(!physic_is_set(&pplayer->vphysic)) - { - physic_set_state(&pplayer->vphysic,PH_VT); - physic_set_start_vy(&pplayer->vphysic,0); - } - } - pplayer->base.ym = physic_get_velocity(&pplayer->vphysic); - - } - else - { - - /* Land: */ - - if (pplayer->base.ym > 0) - { - pplayer->base.y = (int)(((int)pplayer->base.y / 32) * 32); - pplayer->base.ym = 0; - } - - physic_init(&pplayer->vphysic); - - /* Reset score multiplier (for multi-hits): */ - - score_multiplier = 1; - } - - if(jumped_in_solid == YES) - { - - if (isbrick(pplayer->base.x, pplayer->base.y) || - isfullbox(pplayer->base.x, pplayer->base.y)) - { - trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE); - trybumpbadguy(pplayer->base.x, pplayer->base.y - 64); - - if(pplayer->size == BIG) - trybreakbrick(pplayer->base.x, pplayer->base.y); - - bumpbrick(pplayer->base.x, pplayer->base.y); - tryemptybox(pplayer->base.x, pplayer->base.y, RIGHT); - } - - if (isbrick(pplayer->base.x+ 31, pplayer->base.y) || - isfullbox(pplayer->base.x+ 31, pplayer->base.y)) - { - trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE); - trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64); - - if(pplayer->size == BIG) - trybreakbrick(pplayer->base.x+ 31, pplayer->base.y); - - bumpbrick(pplayer->base.x+ 31, pplayer->base.y); - tryemptybox(pplayer->base.x+ 31, pplayer->base.y, LEFT); - } - - - if(pplayer->size == SMALL) - { - /* Get a distro from a brick? */ - - if (shape(pplayer->base.x, pplayer->base.y) == 'x' || - shape(pplayer->base.x, pplayer->base.y) == 'y') - { - add_bouncy_distro((((int)pplayer->base.x) - / 32) * 32, - ((int)pplayer->base.y / 32) * 32); - if (counting_distros == NO) - { - counting_distros = YES; - distro_counter = 100; - } - - if (distro_counter <= 0) - level_change(¤t_level,pplayer->base.x,pplayer->base.y - 1, 'a'); - - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); - score = score + SCORE_DISTRO; - distros++; - } - else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' || - shape(pplayer->base.x+ 31, pplayer->base.y) == 'y') - { - add_bouncy_distro((((int)pplayer->base.x + 31) - / 32) * 32, - ((int)pplayer->base.y / 32) * 32); - if (counting_distros == NO) - { - counting_distros = YES; - distro_counter = 100; - } - - if (distro_counter <= 0) - level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a'); - - play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); - score = score + SCORE_DISTRO; - distros++; - } - } - } - - player_grabdistros(pplayer); - if(jumped_in_solid == YES) - { - ++pplayer->base.y; - ++pplayer->old_base.y; - if(player_on_ground(pplayer)) - { - /* Make sure jumping is off. */ - pplayer->jumping = NO; - } - } - - } - - timer_check(&pplayer->safe_timer); - - - /* ---- DONE HANDLING TUX! --- */ - - /* Handle invincibility timer: */ - - - if (get_current_music() == HERRING_MUSIC && !timer_check(&pplayer->invincible_timer)) - { - /* - no, we are no more invincible - or we were not in invincible mode - but are we in hurry ? - */ - - - if (timer_get_left(&time_left) < TIME_WARNING) - { - /* yes, we are in hurry - stop the herring_song, prepare to play the correct - fast level_song ! - */ - set_current_music(HURRYUP_MUSIC); - } - else - { - set_current_music(LEVEL_MUSIC); - } - - /* start playing it */ - play_current_music(); - } - - /* Handle skidding: */ - - timer_check(&pplayer->skidding_timer); - - /* End of level? */ - - if (pplayer->base.x >= endpos && endpos != 0) - { - next_level = 1; - } - -} - -int player_on_ground(player_type *pplayer) -{ - if( issolid(pplayer->base.x + pplayer->base.width / 2, pplayer->base.y + pplayer->base.height) || - issolid(pplayer->base.x + 1, pplayer->base.y + pplayer->base.height) || - issolid(pplayer->base.x + pplayer->base.width - 1, pplayer->base.y + pplayer->base.height) ) - { - return YES; - } - else - { - return NO; - } -} - -int player_under_solid(player_type *pplayer) -{ - if( issolid(pplayer->base.x + pplayer->base.width / 2, pplayer->base.y) || - issolid(pplayer->base.x + 1, pplayer->base.y) || - issolid(pplayer->base.x + pplayer->base.width - 1, pplayer->base.y) ) - { - return YES; - } - else - { - return NO; - } -} - -void player_handle_horizontal_input(player_type *pplayer, int dir) -{ - - if ((dir ? (pplayer->base.xm < -SKID_XM) : (pplayer->base.xm > SKID_XM)) && !timer_started(&pplayer->skidding_timer) && - pplayer->dir == !dir && player_on_ground(pplayer)) - { - timer_start(&pplayer->skidding_timer, SKID_TIME); - - play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER); - - } - pplayer->dir = dir; - - - if ((dir ? (pplayer->base.xm < 0) : (pplayer->base.xm > 0)) && !isice(pplayer->base.x, pplayer->base.y + pplayer->base.height) && - !timer_started(&pplayer->skidding_timer)) - { - pplayer->base.xm = 0; - } - - if (!pplayer->duck) - { - if (pplayer->dir == dir) - { - /* Facing the direction we're jumping? Go full-speed: */ - - if (pplayer->input.fire == UP) - { - pplayer->base.xm = pplayer->base.xm + ( dir ? WALK_SPEED : -WALK_SPEED) * frame_ratio; - - if(dir) - { - if (pplayer->base.xm > MAX_WALK_XM) - pplayer->base.xm = MAX_WALK_XM; - } - else - { - if (pplayer->base.xm < -MAX_WALK_XM) - pplayer->base.xm = -MAX_WALK_XM; - } - } - else if ( pplayer->input.fire == DOWN) - { - pplayer->base.xm = pplayer->base.xm + ( dir ? RUN_SPEED : -RUN_SPEED) * frame_ratio; - - if(dir) - { - if (pplayer->base.xm > MAX_RUN_XM) - pplayer->base.xm = MAX_RUN_XM; - } - else - { - if (pplayer->base.xm < -MAX_RUN_XM) - pplayer->base.xm = -MAX_RUN_XM; - } - } - else - { - /* Not facing the direction we're jumping? - Go half-speed: */ - - pplayer->base.xm = pplayer->base.xm + ( dir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio; - - if(dir) - { - if (pplayer->base.xm > MAX_WALK_XM / 2) - pplayer->base.xm = MAX_WALK_XM / 2; - } - else - { - if (pplayer->base.xm < -MAX_WALK_XM / 2) - pplayer->base.xm = -MAX_WALK_XM / 2; - } - } - } - - } -} - -void player_handle_vertical_input(player_type *pplayer) -{ - if(pplayer->input.up == DOWN) - { - if (player_on_ground(pplayer)) - { - if(!physic_is_set(&pplayer->vphysic)) - { - physic_set_state(&pplayer->vphysic,PH_VT); - physic_set_start_vy(&pplayer->vphysic,5.5); - --pplayer->base.y; - pplayer->jumping = YES; - if (pplayer->size == SMALL) - play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER); - else - play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER); - } - } - } - else if(pplayer->input.up == UP && pplayer->jumping == YES) - { - if (player_on_ground(pplayer)) - { - physic_init(&pplayer->vphysic); - pplayer->jumping == NO; - } - else - { - pplayer->jumping = NO; - if(physic_is_set(&pplayer->vphysic)) - { - if(physic_get_velocity(&pplayer->vphysic) < 0.) - { - physic_set_state(&pplayer->vphysic,PH_VT); - physic_set_start_vy(&pplayer->vphysic,0); - } - } - else - { - if(!physic_is_set(&pplayer->vphysic)) - { - physic_set_state(&pplayer->vphysic,PH_VT); - } - } - } - } -} - -void player_input(player_type *pplayer) -{ - /* Handle key and joystick state: */ - - if(pplayer->duck == NO) - { - if (pplayer->input.right == DOWN && pplayer->input.left == UP) - { - player_handle_horizontal_input(pplayer,RIGHT); - } - else if (pplayer->input.left == DOWN && pplayer->input.right == UP) - { - player_handle_horizontal_input(pplayer,LEFT); - } - else - { - if(pplayer->base.xm > 0) - { - pplayer->base.xm = (int)(pplayer->base.xm - frame_ratio); - if(pplayer->base.xm < 0) - pplayer->base.xm = 0; - } - else if(pplayer->base.xm < 0) - { - pplayer->base.xm = (int)(pplayer->base.xm + frame_ratio); - if(pplayer->base.xm > 0) - pplayer->base.xm = 0; - } - } - } - - /* Jump/jumping? */ - - if ( pplayer->input.up == DOWN || (pplayer->input.up == UP && pplayer->jumping == YES)) - { - player_handle_vertical_input(pplayer); - } - - /* Shoot! */ - - if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee) - { - add_bullet(pplayer->base.x, pplayer->base.y, pplayer->base.xm, pplayer->dir); - } - - - /* Duck! */ - - if (pplayer->input.down == DOWN) - { - if (pplayer->size == BIG && pplayer->duck != YES) - { - pplayer->duck = YES; - pplayer->base.height = 32; - pplayer->base.y += 32; - } - } - else - { - if (pplayer->size == BIG && pplayer->duck == YES) - { - /* Make sure we're not standing back up into a solid! */ - pplayer->base.height = 64; - pplayer->base.y -= 32; - - if (!collision_object_map(&pplayer->base) /*issolid(pplayer->base.x + 16, pplayer->base.y - 16)*/) - { - pplayer->duck = NO; - pplayer->base.height = 64; - pplayer->old_base.y -= 32; - pplayer->old_base.height = 64; - } - else - { - pplayer->base.height = 32; - pplayer->base.y += 32; - } - } - else - { - pplayer->duck = NO; - } - } - - /* (Tux): */ - - if(!timer_check(&pplayer->frame_timer)) - { - timer_start(&pplayer->frame_timer,25); - if (pplayer->input.right == UP && pplayer->input.left == UP) - { - pplayer->frame_main = 1; - pplayer->frame = 1; - } - else - { - if ((pplayer->input.fire == DOWN && (frame % 2) == 0) || - (frame % 4) == 0) - pplayer->frame_main = (pplayer->frame_main + 1) % 4; - - pplayer->frame = pplayer->frame_main; - - if (pplayer->frame == 3) - pplayer->frame = 1; - } - } - -} - -void player_grabdistros(player_type *pplayer) -{ - /* Grab distros: */ - if (!pplayer->dying) - { - trygrabdistro(pplayer->base.x, pplayer->base.y, NO_BOUNCE); - trygrabdistro(pplayer->base.x+ 31, pplayer->base.y, NO_BOUNCE); - - trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height, NO_BOUNCE); - trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height, NO_BOUNCE); - - if(pplayer->size == BIG) - { - trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE); - trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE); - } - - } - - - /* Enough distros for a One-up? */ - - if (distros >= DISTROS_LIFEUP) - { - distros = distros - DISTROS_LIFEUP; - if(pplayer->lives < MAX_LIVES) - pplayer->lives++; - /*We want to hear the sound even, if MAX_LIVES is reached*/ - play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER); - } -} - -void player_draw(player_type* pplayer) -{ - if (!timer_started(&pplayer->safe_timer) || (frame % 2) == 0) - { - if (pplayer->size == SMALL) - { - if (timer_started(&pplayer->invincible_timer)) - { - /* Draw cape: */ - - if (pplayer->dir == RIGHT) - { - texture_draw(&cape_right[frame % 2], - pplayer->base.x- scroll_x, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&cape_left[frame % 2], - pplayer->base.x- scroll_x, pplayer->base.y, - NO_UPDATE); - } - } - - - if (!pplayer->got_coffee) - { - if (pplayer->dir == RIGHT) - { - texture_draw(&tux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); - } - else - { - texture_draw(&tux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); - } - } - else - { - /* Tux got coffee! */ - - if (pplayer->dir == RIGHT) - { - texture_draw(&firetux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); - } - else - { - texture_draw(&firetux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); - } - } - } - else - { - if (timer_started(&pplayer->invincible_timer)) - { - /* Draw cape: */ - - if (pplayer->dir == RIGHT) - { - texture_draw(&bigcape_right[frame % 2], - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&bigcape_left[frame % 2], - pplayer->base.x-scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - - if (!pplayer->got_coffee) - { - if (!pplayer->duck) - { - if (!timer_started(&pplayer->skidding_timer)) - { - if (!pplayer->jumping || pplayer->base.ym > 0) - { - if (pplayer->dir == RIGHT) - { - texture_draw(&bigtux_right[pplayer->frame], - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&bigtux_left[pplayer->frame], - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - else - { - if (pplayer->dir == RIGHT) - { - texture_draw(&bigtux_right_jump, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&bigtux_left_jump, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - } - else - { - if (pplayer->dir == RIGHT) - { - texture_draw(&skidtux_right, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&skidtux_left, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - } - else - { - if (pplayer->dir == RIGHT) - { - texture_draw(&ducktux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, - NO_UPDATE); - } - else - { - texture_draw(&ducktux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, - NO_UPDATE); - } - } - } - else - { - /* Tux has coffee! */ - - if (!pplayer->duck) - { - if (!timer_started(&pplayer->skidding_timer)) - { - if (!pplayer->jumping || pplayer->base.ym > 0) - { - if (pplayer->dir == RIGHT) - { - texture_draw(&bigfiretux_right[pplayer->frame], - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&bigfiretux_left[pplayer->frame], - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - else - { - if (pplayer->dir == RIGHT) - { - texture_draw(&bigfiretux_right_jump, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&bigfiretux_left_jump, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - } - else - { - if (pplayer->dir == RIGHT) - { - texture_draw(&skidfiretux_right, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - else - { - texture_draw(&skidfiretux_left, - pplayer->base.x- scroll_x - 8, pplayer->base.y, - NO_UPDATE); - } - } - } - else - { - if (pplayer->dir == RIGHT) - { - texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, - NO_UPDATE); - } - else - { - texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, - NO_UPDATE); - } - } - } - } - } -} - -void player_collision(player_type* pplayer, void* p_c_object, int c_object) -{ - bad_guy_type* pbad_c = NULL; - - switch (c_object) - { - case CO_BADGUY: - pbad_c = (bad_guy_type*) p_c_object; - /* Hurt the player if he just touched it: */ - - if (!pbad_c->dying && !pplayer->dying && - !timer_started(&pplayer->safe_timer) && - pbad_c->mode != HELD) - { - if (pbad_c->mode == FLAT && pplayer->input.fire != DOWN) - { - /* Kick: */ - - pbad_c->mode = KICK; - play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); - - if (pplayer->base.x<= pbad_c->base.x) - { - pbad_c->dir = RIGHT; - pbad_c->base.x = pbad_c->base.x + 16; - } - else - { - pbad_c->dir = LEFT; - pbad_c->base.x = pbad_c->base.x - 32; - } - - timer_start(&pbad_c->timer,5000); - } - else if (pbad_c->mode == FLAT && pplayer->input.fire == DOWN) - { - pbad_c->mode = HELD; - pbad_c->base.y-=8; - } - else if (pbad_c->mode == KICK) - { - if (pplayer->base.y < pbad_c->base.y - 16 && - timer_started(&pbad_c->timer)) - { - /* Step on (stop being kicked) */ - - pbad_c->mode = FLAT; - play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); - timer_start(&pbad_c->timer, 10000); - } - else - { - /* Hurt if you get hit by kicked laptop: */ - - if (timer_started(&pbad_c->timer)) - { - if (!timer_started(&pplayer->invincible_timer)) - { - player_kill(pplayer,SHRINK); - } - else - { - pbad_c->dying = FALLING; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - add_score(pbad_c->base.x - scroll_x, - pbad_c->base.y, - 25 * score_multiplier); - } - } - } - } - else - { - if (!timer_started(&pplayer->invincible_timer )) - { - player_kill(pplayer,SHRINK); - } - else - { - pbad_c->dying = FALLING; - play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); - add_score(pbad_c->base.x - scroll_x, - pbad_c->base.y, - 25 * score_multiplier); - } - } - score_multiplier++; - } - break; - default: - break; - } - -} - -/* Kill Player! */ - -void player_kill(player_type* pplayer, int mode) -{ - pplayer->base.ym = -5; - - play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER); - - if (pplayer->dir == RIGHT) - pplayer->base.xm = -8; - else if (pplayer->dir == LEFT) - pplayer->base.xm = 8; - - if (mode == SHRINK && pplayer->size == BIG) - { - if (pplayer->got_coffee) - pplayer->got_coffee = NO; - - pplayer->size = SMALL; - pplayer->base.height = 32; - - timer_start(&pplayer->safe_timer,TUX_SAFE_TIME); - } - else - { - pplayer->dying = 1; - } -} - -void player_dying(player_type *pplayer) -{ - pplayer->base.ym = pplayer->base.ym + gravity; - - /* He died :^( */ - - --pplayer->lives; - player_remove_powerups(pplayer); - pplayer->dying = NO; - - player_level_begin(pplayer); - -} - -/* Remove Tux's power ups */ -void player_remove_powerups(player_type* pplayer) -{ - pplayer->got_coffee = NO; - pplayer->size = SMALL; - pplayer->base.height = 32; -} - -void player_keep_in_bounds(player_type* pplayer) -{ - /* Keep tux in bounds: */ - if (pplayer->base.x< 0) - pplayer->base.x= 0; - else if(pplayer->base.x< scroll_x) - pplayer->base.x= scroll_x; - else if (pplayer->base.x< 160 + scroll_x && scroll_x > 0 && debug_mode == YES) - { - scroll_x = pplayer->base.x- 160; - /*pplayer->base.x+= 160;*/ - - if(scroll_x < 0) - scroll_x = 0; - - } - else if (pplayer->base.x> screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w)) - { - /* Scroll the screen in past center: */ - - scroll_x = pplayer->base.x- screen->w / 2; - /*pplayer->base.x= 320 + scroll_x;*/ - - if (scroll_x > ((current_level.width * 32) - screen->w)) - scroll_x = ((current_level.width * 32) - screen->w); - } - else if (pplayer->base.x> 608 + scroll_x) - { - /* ... unless there's no more to scroll! */ - - /*pplayer->base.x= 608 + scroll_x;*/ - } - - /* Keep in-bounds, vertically: */ - - if (pplayer->base.y > screen->h) - { - player_kill(&tux,KILL); - } -} diff --git a/src/player.cpp b/src/player.cpp new file mode 100644 index 000000000..1f876f3f5 --- /dev/null +++ b/src/player.cpp @@ -0,0 +1,1024 @@ +// +// C Implementation: player/tux +// +// Description: +// +// +// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "gameloop.h" +#include "globals.h" +#include "player.h" +#include "defines.h" +#include "scene.h" +#include "screen.h" + +texture_type tux_life, +tux_right[3], tux_left[3], +bigtux_right[3], bigtux_left[3], +bigtux_right_jump, bigtux_left_jump, +ducktux_right, ducktux_left, +skidtux_right, skidtux_left, +firetux_right[3], firetux_left[3], +bigfiretux_right[3], bigfiretux_left[3], +bigfiretux_right_jump, bigfiretux_left_jump, +duckfiretux_right, duckfiretux_left, +skidfiretux_right, skidfiretux_left, +cape_right[2], cape_left[2], +bigcape_right[2], bigcape_left[2]; + +void player_input_init(player_input_type* pplayer_input) +{ + pplayer_input->down = UP; + pplayer_input->fire = UP; + pplayer_input->left = UP; + pplayer_input->old_fire = UP; + pplayer_input->right = UP; + pplayer_input->up = UP; +} + +void player_init(player_type* pplayer) +{ + pplayer->base.width = 32; + pplayer->base.height = 32; + + pplayer->size = SMALL; + pplayer->got_coffee = NO; + + pplayer->base.x = 0; + pplayer->base.y = 240; + pplayer->base.xm = 0; + pplayer->base.ym = 0; + pplayer->old_base = pplayer->base; + pplayer->dir = RIGHT; + pplayer->duck = NO; + + pplayer->dying = NO; + pplayer->jumping = NO; + + pplayer->frame_main = 0; + pplayer->frame = 0; + pplayer->lives = 3; + pplayer->score = 0; + pplayer->distros = 0; + + player_input_init(&pplayer->input); + + pplayer->keymap.jump = SDLK_UP; + pplayer->keymap.duck = SDLK_DOWN; + pplayer->keymap.left = SDLK_LEFT; + pplayer->keymap.right = SDLK_RIGHT; + pplayer->keymap.fire = SDLK_LCTRL; + + timer_init(&pplayer->invincible_timer,YES); + timer_init(&pplayer->skidding_timer,YES); + timer_init(&pplayer->safe_timer,YES); + timer_init(&pplayer->frame_timer,YES); + physic_init(&pplayer->hphysic); + physic_init(&pplayer->vphysic); +} + +int player_key_event(player_type* pplayer, SDLKey key, int state) +{ + if(key == pplayer->keymap.right) + { + pplayer->input.right = state; + return YES; + } + else if( key == pplayer->keymap.left) + { + pplayer->input.left = state; + return YES; + } + else if(key == pplayer->keymap.jump) + { + pplayer->input.up = state; + return YES; + } + else if(key == pplayer->keymap.duck) + { + pplayer->input.down = state; + return YES; + } + else if(key == pplayer->keymap.fire) + { + pplayer->input.fire = state; + return YES; + } + else + return NO; +} + +void player_level_begin(player_type* pplayer) +{ + pplayer->base.x = 0; + pplayer->base.y = 240; + pplayer->base.xm = 0; + pplayer->base.ym = 0; + pplayer->old_base = pplayer->base; + + player_input_init(&pplayer->input); + + timer_init(&pplayer->invincible_timer,YES); + timer_init(&pplayer->skidding_timer,YES); + timer_init(&pplayer->safe_timer,YES); + timer_init(&pplayer->frame_timer,YES); + physic_init(&pplayer->hphysic); + physic_init(&pplayer->vphysic); +} + +void player_action(player_type* pplayer) +{ + int i, jumped_in_solid; + jumped_in_solid = NO; + + /* --- HANDLE TUX! --- */ + + player_input(pplayer); + + /* Move tux: */ + + pplayer->previous_base = pplayer->base; + + pplayer->base.x += pplayer->base.xm * frame_ratio; + pplayer->base.y += pplayer->base.ym * frame_ratio; + + collision_swept_object_map(&pplayer->old_base,&pplayer->base); + + player_keep_in_bounds(pplayer); + + /* Land: */ + + if (!pplayer->dying) + { + + + if( !player_on_ground(pplayer)) + { + if(player_under_solid(pplayer)) + { + physic_set_state(&pplayer->vphysic,PH_VT); + physic_set_start_vy(&pplayer->vphysic,0); + jumped_in_solid = YES; + } + else + { + if(!physic_is_set(&pplayer->vphysic)) + { + physic_set_state(&pplayer->vphysic,PH_VT); + physic_set_start_vy(&pplayer->vphysic,0); + } + } + pplayer->base.ym = physic_get_velocity(&pplayer->vphysic); + + } + else + { + + /* Land: */ + + if (pplayer->base.ym > 0) + { + pplayer->base.y = (int)(((int)pplayer->base.y / 32) * 32); + pplayer->base.ym = 0; + } + + physic_init(&pplayer->vphysic); + + /* Reset score multiplier (for multi-hits): */ + + score_multiplier = 1; + } + + if(jumped_in_solid == YES) + { + + if (isbrick(pplayer->base.x, pplayer->base.y) || + isfullbox(pplayer->base.x, pplayer->base.y)) + { + trygrabdistro(pplayer->base.x, pplayer->base.y - 32,BOUNCE); + trybumpbadguy(pplayer->base.x, pplayer->base.y - 64); + + if(pplayer->size == BIG) + trybreakbrick(pplayer->base.x, pplayer->base.y); + + bumpbrick(pplayer->base.x, pplayer->base.y); + tryemptybox(pplayer->base.x, pplayer->base.y, RIGHT); + } + + if (isbrick(pplayer->base.x+ 31, pplayer->base.y) || + isfullbox(pplayer->base.x+ 31, pplayer->base.y)) + { + trygrabdistro(pplayer->base.x+ 31, pplayer->base.y - 32,BOUNCE); + trybumpbadguy(pplayer->base.x+ 31, pplayer->base.y - 64); + + if(pplayer->size == BIG) + trybreakbrick(pplayer->base.x+ 31, pplayer->base.y); + + bumpbrick(pplayer->base.x+ 31, pplayer->base.y); + tryemptybox(pplayer->base.x+ 31, pplayer->base.y, LEFT); + } + + + if(pplayer->size == SMALL) + { + /* Get a distro from a brick? */ + + if (shape(pplayer->base.x, pplayer->base.y) == 'x' || + shape(pplayer->base.x, pplayer->base.y) == 'y') + { + add_bouncy_distro((((int)pplayer->base.x) + / 32) * 32, + ((int)pplayer->base.y / 32) * 32); + if (counting_distros == NO) + { + counting_distros = YES; + distro_counter = 100; + } + + if (distro_counter <= 0) + level_change(¤t_level,pplayer->base.x,pplayer->base.y - 1, 'a'); + + play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + score = score + SCORE_DISTRO; + distros++; + } + else if (shape(pplayer->base.x+ 31, pplayer->base.y) == 'x' || + shape(pplayer->base.x+ 31, pplayer->base.y) == 'y') + { + add_bouncy_distro((((int)pplayer->base.x + 31) + / 32) * 32, + ((int)pplayer->base.y / 32) * 32); + if (counting_distros == NO) + { + counting_distros = YES; + distro_counter = 100; + } + + if (distro_counter <= 0) + level_change(¤t_level,pplayer->base.x+ 31, pplayer->base.y, 'a'); + + play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER); + score = score + SCORE_DISTRO; + distros++; + } + } + } + + player_grabdistros(pplayer); + if(jumped_in_solid == YES) + { + ++pplayer->base.y; + ++pplayer->old_base.y; + if(player_on_ground(pplayer)) + { + /* Make sure jumping is off. */ + pplayer->jumping = NO; + } + } + + } + + timer_check(&pplayer->safe_timer); + + + /* ---- DONE HANDLING TUX! --- */ + + /* Handle invincibility timer: */ + + + if (get_current_music() == HERRING_MUSIC && !timer_check(&pplayer->invincible_timer)) + { + /* + no, we are no more invincible + or we were not in invincible mode + but are we in hurry ? + */ + + + if (timer_get_left(&time_left) < TIME_WARNING) + { + /* yes, we are in hurry + stop the herring_song, prepare to play the correct + fast level_song ! + */ + set_current_music(HURRYUP_MUSIC); + } + else + { + set_current_music(LEVEL_MUSIC); + } + + /* start playing it */ + play_current_music(); + } + + /* Handle skidding: */ + + timer_check(&pplayer->skidding_timer); + + /* End of level? */ + + if (pplayer->base.x >= endpos && endpos != 0) + { + next_level = 1; + } + +} + +int player_on_ground(player_type *pplayer) +{ + if( issolid(pplayer->base.x + pplayer->base.width / 2, pplayer->base.y + pplayer->base.height) || + issolid(pplayer->base.x + 1, pplayer->base.y + pplayer->base.height) || + issolid(pplayer->base.x + pplayer->base.width - 1, pplayer->base.y + pplayer->base.height) ) + { + return YES; + } + else + { + return NO; + } +} + +int player_under_solid(player_type *pplayer) +{ + if( issolid(pplayer->base.x + pplayer->base.width / 2, pplayer->base.y) || + issolid(pplayer->base.x + 1, pplayer->base.y) || + issolid(pplayer->base.x + pplayer->base.width - 1, pplayer->base.y) ) + { + return YES; + } + else + { + return NO; + } +} + +void player_handle_horizontal_input(player_type *pplayer, int dir) +{ + + if ((dir ? (pplayer->base.xm < -SKID_XM) : (pplayer->base.xm > SKID_XM)) && !timer_started(&pplayer->skidding_timer) && + pplayer->dir == !dir && player_on_ground(pplayer)) + { + timer_start(&pplayer->skidding_timer, SKID_TIME); + + play_sound(sounds[SND_SKID], SOUND_CENTER_SPEAKER); + + } + pplayer->dir = dir; + + + if ((dir ? (pplayer->base.xm < 0) : (pplayer->base.xm > 0)) && !isice(pplayer->base.x, pplayer->base.y + pplayer->base.height) && + !timer_started(&pplayer->skidding_timer)) + { + pplayer->base.xm = 0; + } + + if (!pplayer->duck) + { + if (pplayer->dir == dir) + { + /* Facing the direction we're jumping? Go full-speed: */ + + if (pplayer->input.fire == UP) + { + pplayer->base.xm = pplayer->base.xm + ( dir ? WALK_SPEED : -WALK_SPEED) * frame_ratio; + + if(dir) + { + if (pplayer->base.xm > MAX_WALK_XM) + pplayer->base.xm = MAX_WALK_XM; + } + else + { + if (pplayer->base.xm < -MAX_WALK_XM) + pplayer->base.xm = -MAX_WALK_XM; + } + } + else if ( pplayer->input.fire == DOWN) + { + pplayer->base.xm = pplayer->base.xm + ( dir ? RUN_SPEED : -RUN_SPEED) * frame_ratio; + + if(dir) + { + if (pplayer->base.xm > MAX_RUN_XM) + pplayer->base.xm = MAX_RUN_XM; + } + else + { + if (pplayer->base.xm < -MAX_RUN_XM) + pplayer->base.xm = -MAX_RUN_XM; + } + } + else + { + /* Not facing the direction we're jumping? + Go half-speed: */ + + pplayer->base.xm = pplayer->base.xm + ( dir ? (WALK_SPEED / 2) : -(WALK_SPEED / 2)) * frame_ratio; + + if(dir) + { + if (pplayer->base.xm > MAX_WALK_XM / 2) + pplayer->base.xm = MAX_WALK_XM / 2; + } + else + { + if (pplayer->base.xm < -MAX_WALK_XM / 2) + pplayer->base.xm = -MAX_WALK_XM / 2; + } + } + } + + } +} + +void player_handle_vertical_input(player_type *pplayer) +{ + if(pplayer->input.up == DOWN) + { + if (player_on_ground(pplayer)) + { + if(!physic_is_set(&pplayer->vphysic)) + { + physic_set_state(&pplayer->vphysic,PH_VT); + physic_set_start_vy(&pplayer->vphysic,5.5); + --pplayer->base.y; + pplayer->jumping = YES; + if (pplayer->size == SMALL) + play_sound(sounds[SND_JUMP], SOUND_CENTER_SPEAKER); + else + play_sound(sounds[SND_BIGJUMP], SOUND_CENTER_SPEAKER); + } + } + } + else if(pplayer->input.up == UP && pplayer->jumping == YES) + { + if (player_on_ground(pplayer)) + { + physic_init(&pplayer->vphysic); + pplayer->jumping == NO; + } + else + { + pplayer->jumping = NO; + if(physic_is_set(&pplayer->vphysic)) + { + if(physic_get_velocity(&pplayer->vphysic) < 0.) + { + physic_set_state(&pplayer->vphysic,PH_VT); + physic_set_start_vy(&pplayer->vphysic,0); + } + } + else + { + if(!physic_is_set(&pplayer->vphysic)) + { + physic_set_state(&pplayer->vphysic,PH_VT); + } + } + } + } +} + +void player_input(player_type *pplayer) +{ + /* Handle key and joystick state: */ + + if(pplayer->duck == NO) + { + if (pplayer->input.right == DOWN && pplayer->input.left == UP) + { + player_handle_horizontal_input(pplayer,RIGHT); + } + else if (pplayer->input.left == DOWN && pplayer->input.right == UP) + { + player_handle_horizontal_input(pplayer,LEFT); + } + else + { + if(pplayer->base.xm > 0) + { + pplayer->base.xm = (int)(pplayer->base.xm - frame_ratio); + if(pplayer->base.xm < 0) + pplayer->base.xm = 0; + } + else if(pplayer->base.xm < 0) + { + pplayer->base.xm = (int)(pplayer->base.xm + frame_ratio); + if(pplayer->base.xm > 0) + pplayer->base.xm = 0; + } + } + } + + /* Jump/jumping? */ + + if ( pplayer->input.up == DOWN || (pplayer->input.up == UP && pplayer->jumping == YES)) + { + player_handle_vertical_input(pplayer); + } + + /* Shoot! */ + + if (pplayer->input.fire == DOWN && pplayer->input.old_fire == UP && pplayer->got_coffee) + { + add_bullet(pplayer->base.x, pplayer->base.y, pplayer->base.xm, pplayer->dir); + } + + + /* Duck! */ + + if (pplayer->input.down == DOWN) + { + if (pplayer->size == BIG && pplayer->duck != YES) + { + pplayer->duck = YES; + pplayer->base.height = 32; + pplayer->base.y += 32; + } + } + else + { + if (pplayer->size == BIG && pplayer->duck == YES) + { + /* Make sure we're not standing back up into a solid! */ + pplayer->base.height = 64; + pplayer->base.y -= 32; + + if (!collision_object_map(&pplayer->base) /*issolid(pplayer->base.x + 16, pplayer->base.y - 16)*/) + { + pplayer->duck = NO; + pplayer->base.height = 64; + pplayer->old_base.y -= 32; + pplayer->old_base.height = 64; + } + else + { + pplayer->base.height = 32; + pplayer->base.y += 32; + } + } + else + { + pplayer->duck = NO; + } + } + + /* (Tux): */ + + if(!timer_check(&pplayer->frame_timer)) + { + timer_start(&pplayer->frame_timer,25); + if (pplayer->input.right == UP && pplayer->input.left == UP) + { + pplayer->frame_main = 1; + pplayer->frame = 1; + } + else + { + if ((pplayer->input.fire == DOWN && (frame % 2) == 0) || + (frame % 4) == 0) + pplayer->frame_main = (pplayer->frame_main + 1) % 4; + + pplayer->frame = pplayer->frame_main; + + if (pplayer->frame == 3) + pplayer->frame = 1; + } + } + +} + +void player_grabdistros(player_type *pplayer) +{ + /* Grab distros: */ + if (!pplayer->dying) + { + trygrabdistro(pplayer->base.x, pplayer->base.y, NO_BOUNCE); + trygrabdistro(pplayer->base.x+ 31, pplayer->base.y, NO_BOUNCE); + + trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height, NO_BOUNCE); + trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height, NO_BOUNCE); + + if(pplayer->size == BIG) + { + trygrabdistro(pplayer->base.x, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE); + trygrabdistro(pplayer->base.x+ 31, pplayer->base.y + pplayer->base.height / 2, NO_BOUNCE); + } + + } + + + /* Enough distros for a One-up? */ + + if (distros >= DISTROS_LIFEUP) + { + distros = distros - DISTROS_LIFEUP; + if(pplayer->lives < MAX_LIVES) + pplayer->lives++; + /*We want to hear the sound even, if MAX_LIVES is reached*/ + play_sound(sounds[SND_LIFEUP], SOUND_CENTER_SPEAKER); + } +} + +void player_draw(player_type* pplayer) +{ + if (!timer_started(&pplayer->safe_timer) || (frame % 2) == 0) + { + if (pplayer->size == SMALL) + { + if (timer_started(&pplayer->invincible_timer)) + { + /* Draw cape: */ + + if (pplayer->dir == RIGHT) + { + texture_draw(&cape_right[frame % 2], + pplayer->base.x- scroll_x, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&cape_left[frame % 2], + pplayer->base.x- scroll_x, pplayer->base.y, + NO_UPDATE); + } + } + + + if (!pplayer->got_coffee) + { + if (pplayer->dir == RIGHT) + { + texture_draw(&tux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); + } + else + { + texture_draw(&tux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); + } + } + else + { + /* Tux got coffee! */ + + if (pplayer->dir == RIGHT) + { + texture_draw(&firetux_right[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); + } + else + { + texture_draw(&firetux_left[pplayer->frame], pplayer->base.x- scroll_x, pplayer->base.y, NO_UPDATE); + } + } + } + else + { + if (timer_started(&pplayer->invincible_timer)) + { + /* Draw cape: */ + + if (pplayer->dir == RIGHT) + { + texture_draw(&bigcape_right[frame % 2], + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&bigcape_left[frame % 2], + pplayer->base.x-scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + + if (!pplayer->got_coffee) + { + if (!pplayer->duck) + { + if (!timer_started(&pplayer->skidding_timer)) + { + if (!pplayer->jumping || pplayer->base.ym > 0) + { + if (pplayer->dir == RIGHT) + { + texture_draw(&bigtux_right[pplayer->frame], + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&bigtux_left[pplayer->frame], + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + else + { + if (pplayer->dir == RIGHT) + { + texture_draw(&bigtux_right_jump, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&bigtux_left_jump, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + } + else + { + if (pplayer->dir == RIGHT) + { + texture_draw(&skidtux_right, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&skidtux_left, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + } + else + { + if (pplayer->dir == RIGHT) + { + texture_draw(&ducktux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, + NO_UPDATE); + } + else + { + texture_draw(&ducktux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, + NO_UPDATE); + } + } + } + else + { + /* Tux has coffee! */ + + if (!pplayer->duck) + { + if (!timer_started(&pplayer->skidding_timer)) + { + if (!pplayer->jumping || pplayer->base.ym > 0) + { + if (pplayer->dir == RIGHT) + { + texture_draw(&bigfiretux_right[pplayer->frame], + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&bigfiretux_left[pplayer->frame], + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + else + { + if (pplayer->dir == RIGHT) + { + texture_draw(&bigfiretux_right_jump, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&bigfiretux_left_jump, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + } + else + { + if (pplayer->dir == RIGHT) + { + texture_draw(&skidfiretux_right, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + else + { + texture_draw(&skidfiretux_left, + pplayer->base.x- scroll_x - 8, pplayer->base.y, + NO_UPDATE); + } + } + } + else + { + if (pplayer->dir == RIGHT) + { + texture_draw(&duckfiretux_right, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, + NO_UPDATE); + } + else + { + texture_draw(&duckfiretux_left, pplayer->base.x- scroll_x - 8, pplayer->base.y - 16, + NO_UPDATE); + } + } + } + } + } +} + +void player_collision(player_type* pplayer, void* p_c_object, int c_object) +{ + bad_guy_type* pbad_c = NULL; + + switch (c_object) + { + case CO_BADGUY: + pbad_c = (bad_guy_type*) p_c_object; + /* Hurt the player if he just touched it: */ + + if (!pbad_c->dying && !pplayer->dying && + !timer_started(&pplayer->safe_timer) && + pbad_c->mode != HELD) + { + if (pbad_c->mode == FLAT && pplayer->input.fire != DOWN) + { + /* Kick: */ + + pbad_c->mode = KICK; + play_sound(sounds[SND_KICK], SOUND_CENTER_SPEAKER); + + if (pplayer->base.x<= pbad_c->base.x) + { + pbad_c->dir = RIGHT; + pbad_c->base.x = pbad_c->base.x + 16; + } + else + { + pbad_c->dir = LEFT; + pbad_c->base.x = pbad_c->base.x - 32; + } + + timer_start(&pbad_c->timer,5000); + } + else if (pbad_c->mode == FLAT && pplayer->input.fire == DOWN) + { + pbad_c->mode = HELD; + pbad_c->base.y-=8; + } + else if (pbad_c->mode == KICK) + { + if (pplayer->base.y < pbad_c->base.y - 16 && + timer_started(&pbad_c->timer)) + { + /* Step on (stop being kicked) */ + + pbad_c->mode = FLAT; + play_sound(sounds[SND_STOMP], SOUND_CENTER_SPEAKER); + timer_start(&pbad_c->timer, 10000); + } + else + { + /* Hurt if you get hit by kicked laptop: */ + + if (timer_started(&pbad_c->timer)) + { + if (!timer_started(&pplayer->invincible_timer)) + { + player_kill(pplayer,SHRINK); + } + else + { + pbad_c->dying = FALLING; + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + add_score(pbad_c->base.x - scroll_x, + pbad_c->base.y, + 25 * score_multiplier); + } + } + } + } + else + { + if (!timer_started(&pplayer->invincible_timer )) + { + player_kill(pplayer,SHRINK); + } + else + { + pbad_c->dying = FALLING; + play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER); + add_score(pbad_c->base.x - scroll_x, + pbad_c->base.y, + 25 * score_multiplier); + } + } + score_multiplier++; + } + break; + default: + break; + } + +} + +/* Kill Player! */ + +void player_kill(player_type* pplayer, int mode) +{ + pplayer->base.ym = -5; + + play_sound(sounds[SND_HURT], SOUND_CENTER_SPEAKER); + + if (pplayer->dir == RIGHT) + pplayer->base.xm = -8; + else if (pplayer->dir == LEFT) + pplayer->base.xm = 8; + + if (mode == SHRINK && pplayer->size == BIG) + { + if (pplayer->got_coffee) + pplayer->got_coffee = NO; + + pplayer->size = SMALL; + pplayer->base.height = 32; + + timer_start(&pplayer->safe_timer,TUX_SAFE_TIME); + } + else + { + pplayer->dying = 1; + } +} + +void player_dying(player_type *pplayer) +{ + pplayer->base.ym = pplayer->base.ym + gravity; + + /* He died :^( */ + + --pplayer->lives; + player_remove_powerups(pplayer); + pplayer->dying = NO; + + player_level_begin(pplayer); + +} + +/* Remove Tux's power ups */ +void player_remove_powerups(player_type* pplayer) +{ + pplayer->got_coffee = NO; + pplayer->size = SMALL; + pplayer->base.height = 32; +} + +void player_keep_in_bounds(player_type* pplayer) +{ + /* Keep tux in bounds: */ + if (pplayer->base.x< 0) + pplayer->base.x= 0; + else if(pplayer->base.x< scroll_x) + pplayer->base.x= scroll_x; + else if (pplayer->base.x< 160 + scroll_x && scroll_x > 0 && debug_mode == YES) + { + scroll_x = pplayer->base.x- 160; + /*pplayer->base.x+= 160;*/ + + if(scroll_x < 0) + scroll_x = 0; + + } + else if (pplayer->base.x> screen->w / 2 + scroll_x && scroll_x < ((current_level.width * 32) - screen->w)) + { + /* Scroll the screen in past center: */ + + scroll_x = pplayer->base.x- screen->w / 2; + /*pplayer->base.x= 320 + scroll_x;*/ + + if (scroll_x > ((current_level.width * 32) - screen->w)) + scroll_x = ((current_level.width * 32) - screen->w); + } + else if (pplayer->base.x> 608 + scroll_x) + { + /* ... unless there's no more to scroll! */ + + /*pplayer->base.x= 608 + scroll_x;*/ + } + + /* Keep in-bounds, vertically: */ + + if (pplayer->base.y > screen->h) + { + player_kill(&tux,KILL); + } +} diff --git a/src/scene.c b/src/scene.c deleted file mode 100644 index 1748e456a..000000000 --- a/src/scene.c +++ /dev/null @@ -1,302 +0,0 @@ -// -// C Implementation: scene -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include -#include "scene.h" - -int score, distros, level, next_level, game_pause, quit, score_multiplier, endpos, counting_distros, distro_counter; -timer_type super_bkgd_timer; -float scroll_x; -int frame; -bouncy_distro_type *bouncy_distros; -broken_brick_type *broken_bricks; -bouncy_brick_type *bouncy_bricks; -bad_guy_type *bad_guys; -floating_score_type *floating_scores; -upgrade_type *upgrades; -bullet_type *bullets; -int num_bad_guys; -int num_bouncy_distros; -int num_broken_bricks; -int num_bouncy_bricks; -int num_floating_scores; -int num_upgrades; -int num_bullets; -player_type tux; -texture_type img_box_full, img_box_empty, img_mints, img_coffee, img_super_bkgd, img_red_glow; -timer_type time_left; -double frame_ratio; - -/* Initialize all 'dynamic' arrays */ -void arrays_init(void) -{ -num_bad_guys = 0; -num_bouncy_distros = 0; -num_broken_bricks = 0; -num_bouncy_bricks = 0; -num_floating_scores = 0; -num_upgrades = 0; -num_bullets = 0; -bad_guys = NULL; -bouncy_distros = NULL; -broken_bricks = NULL; -bouncy_bricks = NULL; -floating_scores = NULL; -upgrades = NULL; -bullets = NULL; -} - -/* Free memory of 'dynamic' arrays */ -void arrays_free(void) -{ -free(bad_guys); -free(bouncy_distros); -free(broken_bricks); -free(bouncy_bricks); -free(floating_scores); -free(upgrades); -free(bullets); -} - -void set_defaults(void) -{ - /* Set defaults: */ - - scroll_x = 0; - - score_multiplier = 1; - timer_init(&super_bkgd_timer, YES); - - counting_distros = NO; - distro_counter = 0; - - endpos = 0; - - /* set current song/music */ - set_current_music(LEVEL_MUSIC); -} - -/* Add score: */ - -void add_score(float x, float y, int s) -{ - int i, found; - - - /* Add the score: */ - - score += s; - - - /* Add a floating score thing to the game: */ - - found = -1; - - for (i = 0; i < num_floating_scores && found == -1; i++) - { - if (!floating_scores[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_floating_scores; - floating_scores = (floating_score_type*) realloc(floating_scores,num_floating_scores*sizeof(floating_score_type)); - floating_score_init(&floating_scores[num_floating_scores-1],x,y,s); - found = -1; - } - - if (found != -1) - { - floating_score_init(&floating_scores[found],x,y,s); - } -} - -/* Add a bouncy distro: */ - -void add_bouncy_distro(float x, float y) -{ - int i, found; - - found = -1; - - for (i = 0; i < num_bouncy_distros && found == -1; i++) - { - if (!bouncy_distros[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_bouncy_distros; - bouncy_distros = (bouncy_distro_type*) realloc(bouncy_distros,num_bouncy_distros*sizeof(bouncy_distro_type)); - found = num_bouncy_distros - 1; - } - - if (found != -1) - { - bouncy_distro_init(&bouncy_distros[found],x,y); - } -} - - -/* Add broken brick pieces: */ - -void add_broken_brick(float x, float y) -{ - add_broken_brick_piece(x, y, -1, -4); - add_broken_brick_piece(x, y + 16, -1.5, -3); - - add_broken_brick_piece(x + 16, y, 1, -4); - add_broken_brick_piece(x + 16, y + 16, 1.5, -3); -} - - -/* Add a broken brick piece: */ - -void add_broken_brick_piece(float x, float y, float xm, float ym) -{ - int i, found; - - found = -1; - - for (i = 0; i < num_broken_bricks && found == -1; i++) - { - if (!broken_bricks[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_broken_bricks; - broken_bricks = (broken_brick_type*) realloc(broken_bricks,num_broken_bricks*sizeof(broken_brick_type)); - found = num_broken_bricks - 1; - } - - if (found != -1) - { - broken_brick_init(&broken_bricks[found], x, y, xm, ym); - } -} - - -/* Add a bouncy brick piece: */ - -void add_bouncy_brick(float x, float y) -{ - int i, found; - - found = -1; - - for (i = 0; i < num_bouncy_bricks && found == -1; i++) - { - if (!bouncy_bricks[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_bouncy_bricks; - bouncy_bricks = (bouncy_brick_type*) realloc(bouncy_bricks,num_bouncy_bricks*sizeof(bouncy_brick_type)); - found = num_bouncy_bricks - 1; - } - - if (found != -1) - { - bouncy_brick_init(&bouncy_bricks[found],x,y); - } -} - - -/* Add a bad guy: */ - -void add_bad_guy(float x, float y, int kind) -{ - int i, found; - - found = -1; - - for (i = 0; i < num_bad_guys && found == -1; i++) - { - if (!bad_guys[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_bad_guys; - bad_guys = (bad_guy_type*) realloc(bad_guys,num_bad_guys*sizeof(bad_guy_type)); - found = num_bad_guys - 1; - } - - if (found != -1) - { - badguy_init(&bad_guys[found], x, y, kind); - } -} - -/* Add an upgrade: */ - -void add_upgrade(float x, float y, int dir, int kind) -{ - int i, found; - - found = -1; - - for (i = 0; i < num_upgrades && found == -1; i++) - { - if (!upgrades[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_upgrades; - upgrades = (upgrade_type*) realloc(upgrades,num_upgrades*sizeof(upgrade_type)); - found = num_upgrades - 1; - } - - if (found != -1) - { - upgrade_init(&upgrades[found], x, y, dir, kind); - } -} - -/* Add a bullet: */ - -void add_bullet(float x, float y, float xm, int dir) -{ - int i, found; - - found = -1; - - for (i = 0; i < num_bullets && found == -1; i++) - { - if (!bullets[i].base.alive) - found = i; - } - - if (found == -1) - { - ++num_bullets; - bullets = (bullet_type*) realloc(bullets,num_bullets*sizeof(bullet_type)); - found = num_bullets - 1; - } - - if (found != -1) - { - bullet_init(&bullets[found], x, y, xm, dir); - - play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER); - } -} - diff --git a/src/scene.cpp b/src/scene.cpp new file mode 100644 index 000000000..1748e456a --- /dev/null +++ b/src/scene.cpp @@ -0,0 +1,302 @@ +// +// C Implementation: scene +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include "scene.h" + +int score, distros, level, next_level, game_pause, quit, score_multiplier, endpos, counting_distros, distro_counter; +timer_type super_bkgd_timer; +float scroll_x; +int frame; +bouncy_distro_type *bouncy_distros; +broken_brick_type *broken_bricks; +bouncy_brick_type *bouncy_bricks; +bad_guy_type *bad_guys; +floating_score_type *floating_scores; +upgrade_type *upgrades; +bullet_type *bullets; +int num_bad_guys; +int num_bouncy_distros; +int num_broken_bricks; +int num_bouncy_bricks; +int num_floating_scores; +int num_upgrades; +int num_bullets; +player_type tux; +texture_type img_box_full, img_box_empty, img_mints, img_coffee, img_super_bkgd, img_red_glow; +timer_type time_left; +double frame_ratio; + +/* Initialize all 'dynamic' arrays */ +void arrays_init(void) +{ +num_bad_guys = 0; +num_bouncy_distros = 0; +num_broken_bricks = 0; +num_bouncy_bricks = 0; +num_floating_scores = 0; +num_upgrades = 0; +num_bullets = 0; +bad_guys = NULL; +bouncy_distros = NULL; +broken_bricks = NULL; +bouncy_bricks = NULL; +floating_scores = NULL; +upgrades = NULL; +bullets = NULL; +} + +/* Free memory of 'dynamic' arrays */ +void arrays_free(void) +{ +free(bad_guys); +free(bouncy_distros); +free(broken_bricks); +free(bouncy_bricks); +free(floating_scores); +free(upgrades); +free(bullets); +} + +void set_defaults(void) +{ + /* Set defaults: */ + + scroll_x = 0; + + score_multiplier = 1; + timer_init(&super_bkgd_timer, YES); + + counting_distros = NO; + distro_counter = 0; + + endpos = 0; + + /* set current song/music */ + set_current_music(LEVEL_MUSIC); +} + +/* Add score: */ + +void add_score(float x, float y, int s) +{ + int i, found; + + + /* Add the score: */ + + score += s; + + + /* Add a floating score thing to the game: */ + + found = -1; + + for (i = 0; i < num_floating_scores && found == -1; i++) + { + if (!floating_scores[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_floating_scores; + floating_scores = (floating_score_type*) realloc(floating_scores,num_floating_scores*sizeof(floating_score_type)); + floating_score_init(&floating_scores[num_floating_scores-1],x,y,s); + found = -1; + } + + if (found != -1) + { + floating_score_init(&floating_scores[found],x,y,s); + } +} + +/* Add a bouncy distro: */ + +void add_bouncy_distro(float x, float y) +{ + int i, found; + + found = -1; + + for (i = 0; i < num_bouncy_distros && found == -1; i++) + { + if (!bouncy_distros[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_bouncy_distros; + bouncy_distros = (bouncy_distro_type*) realloc(bouncy_distros,num_bouncy_distros*sizeof(bouncy_distro_type)); + found = num_bouncy_distros - 1; + } + + if (found != -1) + { + bouncy_distro_init(&bouncy_distros[found],x,y); + } +} + + +/* Add broken brick pieces: */ + +void add_broken_brick(float x, float y) +{ + add_broken_brick_piece(x, y, -1, -4); + add_broken_brick_piece(x, y + 16, -1.5, -3); + + add_broken_brick_piece(x + 16, y, 1, -4); + add_broken_brick_piece(x + 16, y + 16, 1.5, -3); +} + + +/* Add a broken brick piece: */ + +void add_broken_brick_piece(float x, float y, float xm, float ym) +{ + int i, found; + + found = -1; + + for (i = 0; i < num_broken_bricks && found == -1; i++) + { + if (!broken_bricks[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_broken_bricks; + broken_bricks = (broken_brick_type*) realloc(broken_bricks,num_broken_bricks*sizeof(broken_brick_type)); + found = num_broken_bricks - 1; + } + + if (found != -1) + { + broken_brick_init(&broken_bricks[found], x, y, xm, ym); + } +} + + +/* Add a bouncy brick piece: */ + +void add_bouncy_brick(float x, float y) +{ + int i, found; + + found = -1; + + for (i = 0; i < num_bouncy_bricks && found == -1; i++) + { + if (!bouncy_bricks[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_bouncy_bricks; + bouncy_bricks = (bouncy_brick_type*) realloc(bouncy_bricks,num_bouncy_bricks*sizeof(bouncy_brick_type)); + found = num_bouncy_bricks - 1; + } + + if (found != -1) + { + bouncy_brick_init(&bouncy_bricks[found],x,y); + } +} + + +/* Add a bad guy: */ + +void add_bad_guy(float x, float y, int kind) +{ + int i, found; + + found = -1; + + for (i = 0; i < num_bad_guys && found == -1; i++) + { + if (!bad_guys[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_bad_guys; + bad_guys = (bad_guy_type*) realloc(bad_guys,num_bad_guys*sizeof(bad_guy_type)); + found = num_bad_guys - 1; + } + + if (found != -1) + { + badguy_init(&bad_guys[found], x, y, kind); + } +} + +/* Add an upgrade: */ + +void add_upgrade(float x, float y, int dir, int kind) +{ + int i, found; + + found = -1; + + for (i = 0; i < num_upgrades && found == -1; i++) + { + if (!upgrades[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_upgrades; + upgrades = (upgrade_type*) realloc(upgrades,num_upgrades*sizeof(upgrade_type)); + found = num_upgrades - 1; + } + + if (found != -1) + { + upgrade_init(&upgrades[found], x, y, dir, kind); + } +} + +/* Add a bullet: */ + +void add_bullet(float x, float y, float xm, int dir) +{ + int i, found; + + found = -1; + + for (i = 0; i < num_bullets && found == -1; i++) + { + if (!bullets[i].base.alive) + found = i; + } + + if (found == -1) + { + ++num_bullets; + bullets = (bullet_type*) realloc(bullets,num_bullets*sizeof(bullet_type)); + found = num_bullets - 1; + } + + if (found != -1) + { + bullet_init(&bullets[found], x, y, xm, dir); + + play_sound(sounds[SND_SHOOT], SOUND_CENTER_SPEAKER); + } +} + diff --git a/src/screen.c b/src/screen.c deleted file mode 100644 index 40d1e7bdf..000000000 --- a/src/screen.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - screen.c - - Super Tux - Screen Functions - - by Bill Kendrick - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 11, 2000 - March 15, 2004 -*/ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef LINUX -#include -#include -#include -#endif - -#include "defines.h" -#include "globals.h" -#include "screen.h" -#include "setup.h" -#include "type.h" - -/* Needed for line calculations */ -#define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1))) -#define ABS(x) ((x)>0 ? (x) : (-x)) - -/* --- CLEAR SCREEN --- */ - -void clearscreen(int r, int g, int b) -{ -#ifndef NOOPENGL - if(use_gl) - { - glClearColor(r/256, g/256, b/256, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - } - else - { -#endif - - SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, r, g, b)); -#ifndef NOOPENGL - - } -#endif -} - -/* 'Stolen' from the SDL documentation. - * Set the pixel at (x, y) to the given value - * NOTE: The surface must be locked before calling this! - */ -void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) -{ - int bpp = surface->format->BytesPerPixel; - /* Here p is the address to the pixel we want to set */ - Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch(bpp) - { - case 1: - *p = pixel; - break; - - case 2: - *(Uint16 *)p = pixel; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) - { - p[0] = (pixel >> 16) & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = pixel & 0xff; - } - else - { - p[0] = pixel & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = (pixel >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = pixel; - break; - } -} - -/* Draw a single pixel on the screen. */ -void drawpixel(int x, int y, Uint32 pixel) -{ - /* Lock the screen for direct access to the pixels */ - if ( SDL_MUSTLOCK(screen) ) - { - if ( SDL_LockSurface(screen) < 0 ) - { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return; - } - } - - if(!(x < 0 || y < 0 || x > screen->w || y > screen->h)) - putpixel(screen, x, y, pixel); - - if ( SDL_MUSTLOCK(screen) ) - { - SDL_UnlockSurface(screen); - } - /* Update just the part of the display that we've changed */ - SDL_UpdateRect(screen, x, y, 1, 1); -} - -void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a) -{ -#ifndef NOOPENGL - if(use_gl) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(r, g, b,a); - - glBegin(GL_LINES); - glVertex2f(x1, y1); - glVertex2f(x2, y2); - glEnd(); - glDisable(GL_BLEND); - } - else - { -#endif - - /* Basic unantialiased Bresenham line algorithm */ - int lg_delta, sh_delta, cycle, lg_step, sh_step; - Uint32 color = SDL_MapRGBA(screen->format, r, g, b, a); - - lg_delta = x2 - x1; - sh_delta = y2 - y1; - lg_step = SGN(lg_delta); - lg_delta = ABS(lg_delta); - sh_step = SGN(sh_delta); - sh_delta = ABS(sh_delta); - if (sh_delta < lg_delta) - { - cycle = lg_delta >> 1; - while (x1 != x2) - { - drawpixel(x1, y1, color); - cycle += sh_delta; - if (cycle > lg_delta) - { - cycle -= lg_delta; - y1 += sh_step; - } - x1 += lg_step; - } - drawpixel(x1, y1, color); - } - cycle = sh_delta >> 1; - while (y1 != y2) - { - drawpixel(x1, y1, color); - cycle += lg_delta; - if (cycle > sh_delta) - { - cycle -= sh_delta; - x1 += lg_step; - } - y1 += sh_step; - } - drawpixel(x1, y1, color); -#ifndef NOOPENGL - - } -#endif -} - -/* --- FILL A RECT --- */ - -void fillrect(float x, float y, float w, float h, int r, int g, int b, int a) -{ -if(w < 0) - { - x += w; - w = -w; - } -if(h < 0) - { - y += h; - h = -h; - } - -#ifndef NOOPENGL - if(use_gl) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4ub(r, g, b,a); - - glBegin(GL_POLYGON); - glVertex2f(x, y); - glVertex2f(x+w, y); - glVertex2f(x+w, y+h); - glVertex2f(x, y+h); - glEnd(); - glDisable(GL_BLEND); - } - else - { -#endif - SDL_Rect src, rect; - SDL_Surface *temp = NULL; - - rect.x = (int)x; - rect.y = (int)y; - rect.w = (int)w; - rect.h = (int)h; - - if(a != 255) - { - temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, - screen->format->Rmask, - screen->format->Gmask, - screen->format->Bmask, - screen->format->Amask); - - - src.x = 0; - src.y = 0; - src.w = rect.w; - src.h = rect.h; - - SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b)); - - SDL_SetAlpha(temp, SDL_SRCALPHA, a); - - SDL_BlitSurface(temp,0,screen,&rect); - - SDL_FreeSurface(temp); - } - else - SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b)); - -#ifndef NOOPENGL - - } -#endif -} - - -/* --- UPDATE SCREEN --- */ - -void updatescreen(void) -{ - if(use_gl) /*clearscreen(0,0,0);*/ - SDL_GL_SwapBuffers(); - else - SDL_UpdateRect(screen, 0, 0, screen->w, screen->h); -} - -void flipscreen(void) -{ - if(use_gl) - SDL_GL_SwapBuffers(); - else - SDL_Flip(screen); -} - -void update_rect(SDL_Surface *scr, Sint32 x, Sint32 y, Sint32 w, Sint32 h) -{ - if(!use_gl) - SDL_UpdateRect(scr, x, y, w, h); -} - diff --git a/src/screen.cpp b/src/screen.cpp new file mode 100644 index 000000000..40d1e7bdf --- /dev/null +++ b/src/screen.cpp @@ -0,0 +1,283 @@ +/* + screen.c + + Super Tux - Screen Functions + + by Bill Kendrick + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 11, 2000 - March 15, 2004 +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef LINUX +#include +#include +#include +#endif + +#include "defines.h" +#include "globals.h" +#include "screen.h" +#include "setup.h" +#include "type.h" + +/* Needed for line calculations */ +#define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0:(-1))) +#define ABS(x) ((x)>0 ? (x) : (-x)) + +/* --- CLEAR SCREEN --- */ + +void clearscreen(int r, int g, int b) +{ +#ifndef NOOPENGL + if(use_gl) + { + glClearColor(r/256, g/256, b/256, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + } + else + { +#endif + + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, r, g, b)); +#ifndef NOOPENGL + + } +#endif +} + +/* 'Stolen' from the SDL documentation. + * Set the pixel at (x, y) to the given value + * NOTE: The surface must be locked before calling this! + */ +void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) +{ + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to set */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch(bpp) + { + case 1: + *p = pixel; + break; + + case 2: + *(Uint16 *)p = pixel; + break; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) + { + p[0] = (pixel >> 16) & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = pixel & 0xff; + } + else + { + p[0] = pixel & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = (pixel >> 16) & 0xff; + } + break; + + case 4: + *(Uint32 *)p = pixel; + break; + } +} + +/* Draw a single pixel on the screen. */ +void drawpixel(int x, int y, Uint32 pixel) +{ + /* Lock the screen for direct access to the pixels */ + if ( SDL_MUSTLOCK(screen) ) + { + if ( SDL_LockSurface(screen) < 0 ) + { + fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); + return; + } + } + + if(!(x < 0 || y < 0 || x > screen->w || y > screen->h)) + putpixel(screen, x, y, pixel); + + if ( SDL_MUSTLOCK(screen) ) + { + SDL_UnlockSurface(screen); + } + /* Update just the part of the display that we've changed */ + SDL_UpdateRect(screen, x, y, 1, 1); +} + +void drawline(int x1, int y1, int x2, int y2, int r, int g, int b, int a) +{ +#ifndef NOOPENGL + if(use_gl) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub(r, g, b,a); + + glBegin(GL_LINES); + glVertex2f(x1, y1); + glVertex2f(x2, y2); + glEnd(); + glDisable(GL_BLEND); + } + else + { +#endif + + /* Basic unantialiased Bresenham line algorithm */ + int lg_delta, sh_delta, cycle, lg_step, sh_step; + Uint32 color = SDL_MapRGBA(screen->format, r, g, b, a); + + lg_delta = x2 - x1; + sh_delta = y2 - y1; + lg_step = SGN(lg_delta); + lg_delta = ABS(lg_delta); + sh_step = SGN(sh_delta); + sh_delta = ABS(sh_delta); + if (sh_delta < lg_delta) + { + cycle = lg_delta >> 1; + while (x1 != x2) + { + drawpixel(x1, y1, color); + cycle += sh_delta; + if (cycle > lg_delta) + { + cycle -= lg_delta; + y1 += sh_step; + } + x1 += lg_step; + } + drawpixel(x1, y1, color); + } + cycle = sh_delta >> 1; + while (y1 != y2) + { + drawpixel(x1, y1, color); + cycle += lg_delta; + if (cycle > sh_delta) + { + cycle -= sh_delta; + x1 += lg_step; + } + y1 += sh_step; + } + drawpixel(x1, y1, color); +#ifndef NOOPENGL + + } +#endif +} + +/* --- FILL A RECT --- */ + +void fillrect(float x, float y, float w, float h, int r, int g, int b, int a) +{ +if(w < 0) + { + x += w; + w = -w; + } +if(h < 0) + { + y += h; + h = -h; + } + +#ifndef NOOPENGL + if(use_gl) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4ub(r, g, b,a); + + glBegin(GL_POLYGON); + glVertex2f(x, y); + glVertex2f(x+w, y); + glVertex2f(x+w, y+h); + glVertex2f(x, y+h); + glEnd(); + glDisable(GL_BLEND); + } + else + { +#endif + SDL_Rect src, rect; + SDL_Surface *temp = NULL; + + rect.x = (int)x; + rect.y = (int)y; + rect.w = (int)w; + rect.h = (int)h; + + if(a != 255) + { + temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, + screen->format->Rmask, + screen->format->Gmask, + screen->format->Bmask, + screen->format->Amask); + + + src.x = 0; + src.y = 0; + src.w = rect.w; + src.h = rect.h; + + SDL_FillRect(temp, &src, SDL_MapRGB(screen->format, r, g, b)); + + SDL_SetAlpha(temp, SDL_SRCALPHA, a); + + SDL_BlitSurface(temp,0,screen,&rect); + + SDL_FreeSurface(temp); + } + else + SDL_FillRect(screen, &rect, SDL_MapRGB(screen->format, r, g, b)); + +#ifndef NOOPENGL + + } +#endif +} + + +/* --- UPDATE SCREEN --- */ + +void updatescreen(void) +{ + if(use_gl) /*clearscreen(0,0,0);*/ + SDL_GL_SwapBuffers(); + else + SDL_UpdateRect(screen, 0, 0, screen->w, screen->h); +} + +void flipscreen(void) +{ + if(use_gl) + SDL_GL_SwapBuffers(); + else + SDL_Flip(screen); +} + +void update_rect(SDL_Surface *scr, Sint32 x, Sint32 y, Sint32 w, Sint32 h) +{ + if(!use_gl) + SDL_UpdateRect(scr, x, y, w, h); +} + diff --git a/src/setup.c b/src/setup.c deleted file mode 100644 index ecc64baec..000000000 --- a/src/setup.c +++ /dev/null @@ -1,988 +0,0 @@ -/* - setup.c - - Super Tux - Setup - - by Bill Kendrick - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 11, 2000 - March 15, 2004 -*/ - -#include -#include -#include -#include -#include -#include -#include -#ifndef NOOPENGL -#include -#endif - -#ifdef LINUX -#include -#include -#include -#include -#include -#endif - -#include "defines.h" -#include "globals.h" -#include "setup.h" -#include "screen.h" -#include "texture.h" -#include "menu.h" -#include "gameloop.h" - -/* Local function prototypes: */ - -void seticon(void); -void usage(char * prog, int ret); - -/* Does the given file exist and is it accessible? */ -int faccessible(char *filename) -{ - struct stat filestat; - if (stat(filename, &filestat) == -1) - { - return NO; - } - else - { - if(S_ISREG(filestat.st_mode)) - return YES; - else - return NO; - } -} - -/* Can we write to this location? */ -int fwriteable(char *filename) -{ - FILE* fi; - fi = fopen(filename, "wa"); - if (fi == NULL) - { - return NO; - } - return YES; -} - -/* Makes sure a directory is created in either the SuperTux base directory or the SuperTux base directory.*/ -int fcreatedir(char* relative_dir) -{ - char path[1024]; - snprintf(path, 1024, "%s/%s/", st_dir, relative_dir); - if(mkdir(path,0755) != 0) - { - snprintf(path, 1024, "%s/%s/", DATA_PREFIX, relative_dir); - if(mkdir(path,0755) != 0) - { - return NO; - } - else - { - return YES; - } - } - else - { - return YES; - } -} - -/* Get all names of sub-directories in a certain directory. */ -/* Returns the number of sub-directories found. */ -/* Note: The user has to free the allocated space. */ -string_list_type dsubdirs(char *rel_path, char* expected_file) -{ - DIR *dirStructP; - struct dirent *direntp; - int i = 0; - string_list_type sdirs; - char filename[1024]; - char path[1024]; - - string_list_init(&sdirs); - sprintf(path,"%s/%s",st_dir,rel_path); - if((dirStructP = opendir(path)) != NULL) - { - while((direntp = readdir(dirStructP)) != NULL) - { - char absolute_filename[1024]; - struct stat buf; - - sprintf(absolute_filename, "%s/%s", path, direntp->d_name); - - if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode)) - { - if(expected_file != NULL) - { - sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file); - if(!faccessible(filename)) - continue; - } - - string_list_add_item(&sdirs,direntp->d_name); - } - } - closedir(dirStructP); - } - - sprintf(path,"%s/%s",DATA_PREFIX,rel_path); - if((dirStructP = opendir(path)) != NULL) - { - while((direntp = readdir(dirStructP)) != NULL) - { - char absolute_filename[1024]; - struct stat buf; - - sprintf(absolute_filename, "%s/%s", path, direntp->d_name); - - if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode)) - { - if(expected_file != NULL) - { - sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file); - if(!faccessible(filename)) - { - continue; - } - else - { - sprintf(filename,"%s/%s/%s/%s",st_dir,rel_path,direntp->d_name,expected_file); - if(faccessible(filename)) - continue; - } - } - - string_list_add_item(&sdirs,direntp->d_name); - } - } - closedir(dirStructP); - } - - return sdirs; -} - -string_list_type dfiles(char *rel_path, char* glob, char* exception_str) -{ - DIR *dirStructP; - struct dirent *direntp; - int i = 0; - string_list_type sdirs; - char filename[1024]; - char path[1024]; - - string_list_init(&sdirs); - sprintf(path,"%s/%s",st_dir,rel_path); - if((dirStructP = opendir(path)) != NULL) - { - while((direntp = readdir(dirStructP)) != NULL) - { - char absolute_filename[1024]; - struct stat buf; - - sprintf(absolute_filename, "%s/%s", path, direntp->d_name); - - if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode)) - { - if(exception_str != NULL) - { - if(strstr(direntp->d_name,exception_str) != NULL) - continue; - } - if(glob != NULL) - if(strstr(direntp->d_name,glob) == NULL) - continue; - - string_list_add_item(&sdirs,direntp->d_name); - } - } - closedir(dirStructP); - } - - sprintf(path,"%s/%s",DATA_PREFIX,rel_path); - if((dirStructP = opendir(path)) != NULL) - { - while((direntp = readdir(dirStructP)) != NULL) - { - char absolute_filename[1024]; - struct stat buf; - - sprintf(absolute_filename, "%s/%s", path, direntp->d_name); - - if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode)) - { - if(exception_str != NULL) - { - if(strstr(direntp->d_name,exception_str) != NULL) - continue; - } - if(glob != NULL) - if(strstr(direntp->d_name,glob) == NULL) - continue; - - string_list_add_item(&sdirs,direntp->d_name); - } - } - closedir(dirStructP); - } - - return sdirs; -} - -void free_strings(char **strings, int num) -{ - int i; - for(i=0; i < num; ++i) - free(strings[i]); -} - -/* --- SETUP --- */ -/* Set SuperTux configuration and save directories */ -void st_directory_setup(void) -{ - char *home; - char str[1024]; - /* Get home directory (from $HOME variable)... if we can't determine it, - use the current directory ("."): */ - if (getenv("HOME") != NULL) - home = getenv("HOME"); - else - home = "."; - - st_dir = (char *) malloc(sizeof(char) * (strlen(home) + - strlen("/.supertux") + 1)); - strcpy(st_dir, home); - strcat(st_dir, "/.supertux"); - - /* Remove .supertux config-file from old SuperTux versions */ - if(faccessible(st_dir)) - { - remove - (st_dir); - } - - st_save_dir = (char *) malloc(sizeof(char) * (strlen(st_dir) + strlen("/save") + 1)); - - strcpy(st_save_dir,st_dir); - strcat(st_save_dir,"/save"); - - /* Create them. In the case they exist they won't destroy anything. */ -#ifdef LINUX - - mkdir(st_dir, 0755); - mkdir(st_save_dir, 0755); - - sprintf(str, "%s/levels", st_dir); - mkdir(str, 0755); -#else - #ifdef WIN32 - - mkdir(st_dir); - mkdir(st_save_dir); - sprintf(str, "%s/levels", st_dir); - mkdir(str); -#endif -#endif - -} - -/* Create and setup menus. */ -void st_menu(void) -{ - menu_init(&main_menu); - menu_additem(&main_menu,menu_item_create(MN_LABEL,"Main Menu",0,0)); - menu_additem(&main_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&main_menu,menu_item_create(MN_ACTION,"Start Game",0,0)); - menu_additem(&main_menu,menu_item_create(MN_GOTO,"Load Game",0,&load_game_menu)); - menu_additem(&main_menu,menu_item_create(MN_GOTO,"Options",0,&options_menu)); - menu_additem(&main_menu,menu_item_create(MN_ACTION,"Level editor",0,0)); - menu_additem(&main_menu,menu_item_create(MN_ACTION,"Credits",0,0)); - menu_additem(&main_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&main_menu,menu_item_create(MN_ACTION,"Quit",0,0)); - - menu_init(&options_menu); - menu_additem(&options_menu,menu_item_create(MN_LABEL,"Options",0,0)); - menu_additem(&options_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Fullscreen",use_fullscreen,0)); - if(audio_device == YES) - { - menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Sound ",use_sound,0)); - menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Music ",use_music,0)); - } - else - { - menu_additem(&options_menu,menu_item_create(MN_DEACTIVE,"Sound ",use_sound,0)); - menu_additem(&options_menu,menu_item_create(MN_DEACTIVE,"Music ",use_music,0)); - } - menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Show FPS ",show_fps,0)); - menu_additem(&options_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&options_menu,menu_item_create(MN_BACK,"Back",0,0)); - - menu_init(&load_game_menu); - menu_additem(&load_game_menu,menu_item_create(MN_LABEL,"Load Game",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 1",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 2",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 3",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 4",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 5",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&load_game_menu,menu_item_create(MN_BACK,"Back",0,0)); - - menu_init(&save_game_menu); - menu_additem(&save_game_menu,menu_item_create(MN_LABEL,"Save Game",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 1",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 2",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 3",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 4",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 5",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&save_game_menu,menu_item_create(MN_BACK,"Back",0,0)); - - menu_init(&game_menu); - menu_additem(&game_menu,menu_item_create(MN_LABEL,"InGame Menu",0,0)); - menu_additem(&game_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&game_menu,menu_item_create(MN_ACTION,"Return To Game",0,0)); - menu_additem(&game_menu,menu_item_create(MN_GOTO,"Save Game",0,&save_game_menu)); - menu_additem(&game_menu,menu_item_create(MN_GOTO,"Load Game",0,&load_game_menu)); - menu_additem(&game_menu,menu_item_create(MN_GOTO,"Options",0,&options_menu)); - menu_additem(&game_menu,menu_item_create(MN_HL,"",0,0)); - menu_additem(&game_menu,menu_item_create(MN_ACTION,"Quit Game",0,0)); - - menu_init(&highscore_menu); - menu_additem(&highscore_menu,menu_item_create(MN_TEXTFIELD,"Enter your name:",0,0)); - -} - -void update_load_save_game_menu(menu_type* pmenu, int load) -{ - int i; - - for(i = 2; i < 7; ++i) - { - char *tmp; - slotinfo(&tmp,i-1); - if(load && strlen(tmp) == strlen("Slot X - Free") ) - pmenu->item[i].kind = MN_DEACTIVE; - else - pmenu->item[i].kind = MN_ACTION; - menu_item_change_text(&pmenu->item[i],tmp); - free(tmp); - } -} - -void process_save_load_game_menu(int save) -{ - int slot; - switch (slot = menu_check(save ? &save_game_menu : &load_game_menu)) - { - default: - if(slot != -1) - { - if(save == YES) - { - savegame(slot - 1); - } - else - { - if(game_started == NO) - { - gameloop("default",slot - 1,ST_GL_LOAD_GAME); - show_menu = YES; - menu_set_current(&main_menu); - } - else - loadgame(slot - 1); - } - st_pause_ticks_stop(); - } - break; - } -} - -/* Handle changes made to global settings in the options menu. */ -void process_options_menu(void) -{ - switch (menu_check(&options_menu)) - { - case 2: - if(use_fullscreen != options_menu.item[2].toggled) - { - use_fullscreen = !use_fullscreen; - st_video_setup(); - } - break; - case 3: - if(use_sound != options_menu.item[3].toggled) - use_sound = !use_sound; - break; - case 4: - if(use_music != options_menu.item[4].toggled) - { - if(use_music == YES) - { - if(playing_music()) - { - halt_music(); - } - use_music = NO; - } - else - { - use_music = YES; - if (!playing_music()) - { - play_current_music(); - } - } - } - break; - case 5: - if(show_fps != options_menu.item[5].toggled) - show_fps = !show_fps; - break; - } -} - -void st_general_setup(void) -{ - /* Seed random number generator: */ - - srand(SDL_GetTicks()); - - /* Set icon image: */ - - seticon(); - - /* Unicode needed for input handling: */ - - SDL_EnableUNICODE(1); - - /* Load global images: */ - - text_load(&black_text,DATA_PREFIX "/images/status/letters-black.png", TEXT_TEXT, 16,18); - text_load(&gold_text,DATA_PREFIX "/images/status/letters-gold.png", TEXT_TEXT, 16,18); - text_load(&blue_text,DATA_PREFIX "/images/status/letters-blue.png", TEXT_TEXT, 16,18); - text_load(&red_text,DATA_PREFIX "/images/status/letters-red.png", TEXT_TEXT, 16,18); - text_load(&white_text,DATA_PREFIX "/images/status/letters-white.png", TEXT_TEXT, 16,18); - text_load(&white_small_text,DATA_PREFIX "/images/status/letters-white-small.png", TEXT_TEXT, 8,9); - text_load(&white_big_text,DATA_PREFIX "/images/status/letters-white-big.png", TEXT_TEXT, 20,23); - text_load(&yellow_nums,DATA_PREFIX "/images/status/numbers.png", TEXT_NUM, 32,32); - - /* Load GUI/menu images: */ - texture_load(&checkbox, DATA_PREFIX "/images/status/checkbox.png", USE_ALPHA); - texture_load(&checkbox_checked, DATA_PREFIX "/images/status/checkbox-checked.png", USE_ALPHA); - texture_load(&back, DATA_PREFIX "/images/status/back.png", USE_ALPHA); - texture_load(&arrow_left, DATA_PREFIX "/images/icons/left.png", USE_ALPHA); - texture_load(&arrow_right, DATA_PREFIX "/images/icons/right.png", USE_ALPHA); - -} - -void st_general_free(void) -{ - - /* Free global images: */ - - text_free(&black_text); - text_free(&gold_text); - text_free(&white_text); - text_free(&blue_text); - text_free(&red_text); - text_free(&white_small_text); - text_free(&white_big_text); - - /* Free GUI/menu images: */ - texture_free(&checkbox); - texture_free(&checkbox_checked); - texture_free(&back); - texture_free(&arrow_left); - texture_free(&arrow_right); - - /* Free menus */ - - menu_free(&main_menu); - menu_free(&game_menu); - menu_free(&options_menu); - menu_free(&highscore_menu); - menu_free(&save_game_menu); - menu_free(&load_game_menu); - -} - -void st_video_setup(void) -{ - - if(screen != NULL) - SDL_FreeSurface(screen); - - /* Init SDL Video: */ - - if (SDL_Init(SDL_INIT_VIDEO) < 0) - { - fprintf(stderr, - "\nError: I could not initialize video!\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - exit(1); - } - - /* Open display: */ - - if(use_gl) - st_video_setup_gl(); - else - st_video_setup_sdl(); - - texture_setup(); - - /* Set window manager stuff: */ - - SDL_WM_SetCaption("Super Tux", "Super Tux"); - -} - -void st_video_setup_sdl(void) -{ - SDL_FreeSurface(screen); - - if (use_fullscreen == YES) - { - screen = SDL_SetVideoMode(640, 480, 0, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */ - if (screen == NULL) - { - fprintf(stderr, - "\nWarning: I could not set up fullscreen video for " - "640x480 mode.\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - use_fullscreen = NO; - } - } - else - { - screen = SDL_SetVideoMode(640, 480, 0, SDL_HWSURFACE | SDL_DOUBLEBUF ); - - if (screen == NULL) - { - fprintf(stderr, - "\nError: I could not set up video for 640x480 mode.\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - exit(1); - } - } -} - -void st_video_setup_gl(void) -{ -#ifndef NOOPENGL - - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - - if (use_fullscreen == YES) - { - screen = SDL_SetVideoMode(640, 480, 0, SDL_FULLSCREEN | SDL_OPENGL) ; /* | SDL_HWSURFACE); */ - if (screen == NULL) - { - fprintf(stderr, - "\nWarning: I could not set up fullscreen video for " - "640x480 mode.\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - use_fullscreen = NO; - } - } - else - { - screen = SDL_SetVideoMode(640, 480, 0, SDL_OPENGL); - - if (screen == NULL) - { - fprintf(stderr, - "\nError: I could not set up video for 640x480 mode.\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - exit(1); - } - } - - /* - * Set up OpenGL for 2D rendering. - */ - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - glViewport(0, 0, screen->w, screen->h); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, 0.0f); - -#endif - -} - -void st_joystick_setup(void) -{ - - /* Init Joystick: */ - -#ifdef JOY_YES - use_joystick = YES; - - if (SDL_Init(SDL_INIT_JOYSTICK) < 0) - { - fprintf(stderr, "Warning: I could not initialize joystick!\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - - use_joystick = NO; - } - else - { - /* Open joystick: */ - - if (SDL_NumJoysticks() <= 0) - { - fprintf(stderr, "Warning: No joysticks are available.\n"); - - use_joystick = NO; - } - else - { - js = SDL_JoystickOpen(0); - - if (js == NULL) - { - fprintf(stderr, "Warning: Could not open joystick 1.\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - - use_joystick = NO; - } - else - { - /* Check for proper joystick configuration: */ - - if (SDL_JoystickNumAxes(js) < 2) - { - fprintf(stderr, - "Warning: Joystick does not have enough axes!\n"); - - use_joystick = NO; - } - else - { - if (SDL_JoystickNumButtons(js) < 2) - { - fprintf(stderr, - "Warning: " - "Joystick does not have enough buttons!\n"); - - use_joystick = NO; - } - } - } - } - } -#endif - -} - -void st_audio_setup(void) -{ - - /* Init SDL Audio silently even if --disable-sound : */ - - if (audio_device == YES) - { - if (SDL_Init(SDL_INIT_AUDIO) < 0) - { - /* only print out message if sound or music - was not disabled at command-line - */ - if (use_sound == YES || use_music == YES) - { - fprintf(stderr, - "\nWarning: I could not initialize audio!\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - } - /* keep the programming logic the same :-) - because in this case, use_sound & use_music' values are ignored - when there's no available audio device - */ - use_sound = NO; - use_music = NO; - audio_device = NO; - } - } - - - /* Open sound silently regarless the value of "use_sound": */ - - if (audio_device == YES) - { - if (open_audio(44100, AUDIO_S16, 2, 2048) < 0) - { - /* only print out message if sound or music - was not disabled at command-line - */ - if ((use_sound == YES) || (use_music == YES)) - { - fprintf(stderr, - "\nWarning: I could not set up audio for 44100 Hz " - "16-bit stereo.\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", SDL_GetError()); - } - use_sound = NO; - use_music = NO; - audio_device = NO; - } - } - -} - - -/* --- SHUTDOWN --- */ - -void st_shutdown(void) -{ - close_audio(); - SDL_Quit(); -} - - -/* --- ABORT! --- */ - -void st_abort(char * reason, char * details) -{ - fprintf(stderr, "\nError: %s\n%s\n\n", reason, details); - st_shutdown(); - exit(1); -} - - -/* Set Icon (private) */ - -void seticon(void) -{ - int masklen; - Uint8 * mask; - SDL_Surface * icon; - - - /* Load icon into a surface: */ - - icon = IMG_Load(DATA_PREFIX "/images/icon.png"); - if (icon == NULL) - { - fprintf(stderr, - "\nError: I could not load the icon image: %s\n" - "The Simple DirectMedia error that occured was:\n" - "%s\n\n", DATA_PREFIX "/images/icon.png", SDL_GetError()); - exit(1); - } - - - /* Create mask: */ - - masklen = (((icon -> w) + 7) / 8) * (icon -> h); - mask = (Uint8*) malloc(masklen * sizeof(Uint8)); - memset(mask, 0xFF, masklen); - - - /* Set icon: */ - - SDL_WM_SetIcon(icon, mask); - - - /* Free icon surface & mask: */ - - free(mask); - SDL_FreeSurface(icon); -} - - -/* Parse command-line arguments: */ - -void parseargs(int argc, char * argv[]) -{ - int i; - - /* Set defaults: */ - - - debug_mode = NO; - use_fullscreen = NO; - show_fps = NO; - use_gl = NO; - -#ifndef NOSOUND - - use_sound = YES; - use_music = YES; - audio_device = YES; -#else - - use_sound = NO; - use_music = NO; - audio_device = NO; -#endif - - /* Parse arguments: */ - - for (i = 1; i < argc; i++) - { - if (strcmp(argv[i], "--fullscreen") == 0 || - strcmp(argv[i], "-f") == 0) - { - /* Use full screen: */ - - use_fullscreen = YES; - } - else if (strcmp(argv[i], "--show-fps") == 0) - { - /* Use full screen: */ - - show_fps = YES; - } - else if (strcmp(argv[i], "--opengl") == 0 || - strcmp(argv[i], "-gl") == 0) - { -#ifndef NOOPENGL - /* Use OpengGL: */ - - use_gl = YES; -#endif - - } - else if (strcmp(argv[i], "--usage") == 0) - { - /* Show usage: */ - - usage(argv[0], 0); - } - else if (strcmp(argv[i], "--version") == 0) - { - /* Show version: */ - - printf("Super Tux - version " VERSION "\n"); - exit(0); - } - else if (strcmp(argv[i], "--disable-sound") == 0) - { - /* Disable the compiled in sound feature */ -#ifndef NOSOUND - printf("Sounds disabled \n"); - use_sound = NO; -#else - - printf("Warning: Sound capability has not been compiled into this build.\n"); -#endif - - } - else if (strcmp(argv[i], "--disable-music") == 0) - { - /* Disable the compiled in sound feature */ -#ifndef NOSOUND - printf("Music disabled \n"); - use_music = NO; -#else - - printf("Warning: Music feature is not compiled in \n"); -#endif - - } - else if (strcmp(argv[i], "--debug-mode") == 0) - { - /* Enable the debug-mode */ - debug_mode = YES; - - } - else if (strcmp(argv[i], "--help") == 0) - { /* Show help: */ - - printf("Super Tux " VERSION "\n\n"); - - printf("---------- Command-line options ----------\n\n"); - - printf(" --opengl - If opengl support was compiled in, this will enable the EXPERIMENTAL OpenGL mode.\n\n"); - - printf(" --disable-sound - If sound support was compiled in, this will\n disable sound for this session of the game.\n\n"); - - printf(" --disable-music - Like above, but this will disable music.\n\n"); - - printf(" --fullscreen - Run in fullscreen mode.\n\n"); - - printf(" --debug-mode - Enables the debug-mode, which is useful for developers.\n\n"); - - printf(" --help - Display a help message summarizing command-line\n options, license and game controls.\n\n"); - - printf(" --usage - Display a brief message summarizing command-line options.\n\n"); - - printf(" --version - Display the version of SuperTux you're running.\n\n\n"); - - - printf("---------- License ----------\n\n"); - printf(" This program comes with ABSOLUTELY NO WARRANTY.\n"); - printf(" This is free software, and you are welcome to redistribute\n"); - printf(" or modify it under certain conditions. See the file \n"); - printf(" \"COPYING.txt\" for more details.\n\n\n"); - - printf("---------- Game controls ----------\n\n"); - printf(" Please see the file \"README.txt\"\n\n"); - - exit(0); - } - else - { - /* Unknown - complain! */ - - usage(argv[0], 1); - } - } -} - - -/* Display usage: */ - -void usage(char * prog, int ret) -{ - FILE * fi; - - - /* Determine which stream to write to: */ - - if (ret == 0) - fi = stdout; - else - fi = stderr; - - - /* Display the usage message: */ - - fprintf(fi, "Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug-mode] | [--usage | --help | --version]\n", - prog); - - - /* Quit! */ - - exit(ret); -} - diff --git a/src/setup.cpp b/src/setup.cpp new file mode 100644 index 000000000..ecc64baec --- /dev/null +++ b/src/setup.cpp @@ -0,0 +1,988 @@ +/* + setup.c + + Super Tux - Setup + + by Bill Kendrick + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 11, 2000 - March 15, 2004 +*/ + +#include +#include +#include +#include +#include +#include +#include +#ifndef NOOPENGL +#include +#endif + +#ifdef LINUX +#include +#include +#include +#include +#include +#endif + +#include "defines.h" +#include "globals.h" +#include "setup.h" +#include "screen.h" +#include "texture.h" +#include "menu.h" +#include "gameloop.h" + +/* Local function prototypes: */ + +void seticon(void); +void usage(char * prog, int ret); + +/* Does the given file exist and is it accessible? */ +int faccessible(char *filename) +{ + struct stat filestat; + if (stat(filename, &filestat) == -1) + { + return NO; + } + else + { + if(S_ISREG(filestat.st_mode)) + return YES; + else + return NO; + } +} + +/* Can we write to this location? */ +int fwriteable(char *filename) +{ + FILE* fi; + fi = fopen(filename, "wa"); + if (fi == NULL) + { + return NO; + } + return YES; +} + +/* Makes sure a directory is created in either the SuperTux base directory or the SuperTux base directory.*/ +int fcreatedir(char* relative_dir) +{ + char path[1024]; + snprintf(path, 1024, "%s/%s/", st_dir, relative_dir); + if(mkdir(path,0755) != 0) + { + snprintf(path, 1024, "%s/%s/", DATA_PREFIX, relative_dir); + if(mkdir(path,0755) != 0) + { + return NO; + } + else + { + return YES; + } + } + else + { + return YES; + } +} + +/* Get all names of sub-directories in a certain directory. */ +/* Returns the number of sub-directories found. */ +/* Note: The user has to free the allocated space. */ +string_list_type dsubdirs(char *rel_path, char* expected_file) +{ + DIR *dirStructP; + struct dirent *direntp; + int i = 0; + string_list_type sdirs; + char filename[1024]; + char path[1024]; + + string_list_init(&sdirs); + sprintf(path,"%s/%s",st_dir,rel_path); + if((dirStructP = opendir(path)) != NULL) + { + while((direntp = readdir(dirStructP)) != NULL) + { + char absolute_filename[1024]; + struct stat buf; + + sprintf(absolute_filename, "%s/%s", path, direntp->d_name); + + if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode)) + { + if(expected_file != NULL) + { + sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file); + if(!faccessible(filename)) + continue; + } + + string_list_add_item(&sdirs,direntp->d_name); + } + } + closedir(dirStructP); + } + + sprintf(path,"%s/%s",DATA_PREFIX,rel_path); + if((dirStructP = opendir(path)) != NULL) + { + while((direntp = readdir(dirStructP)) != NULL) + { + char absolute_filename[1024]; + struct stat buf; + + sprintf(absolute_filename, "%s/%s", path, direntp->d_name); + + if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode)) + { + if(expected_file != NULL) + { + sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file); + if(!faccessible(filename)) + { + continue; + } + else + { + sprintf(filename,"%s/%s/%s/%s",st_dir,rel_path,direntp->d_name,expected_file); + if(faccessible(filename)) + continue; + } + } + + string_list_add_item(&sdirs,direntp->d_name); + } + } + closedir(dirStructP); + } + + return sdirs; +} + +string_list_type dfiles(char *rel_path, char* glob, char* exception_str) +{ + DIR *dirStructP; + struct dirent *direntp; + int i = 0; + string_list_type sdirs; + char filename[1024]; + char path[1024]; + + string_list_init(&sdirs); + sprintf(path,"%s/%s",st_dir,rel_path); + if((dirStructP = opendir(path)) != NULL) + { + while((direntp = readdir(dirStructP)) != NULL) + { + char absolute_filename[1024]; + struct stat buf; + + sprintf(absolute_filename, "%s/%s", path, direntp->d_name); + + if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode)) + { + if(exception_str != NULL) + { + if(strstr(direntp->d_name,exception_str) != NULL) + continue; + } + if(glob != NULL) + if(strstr(direntp->d_name,glob) == NULL) + continue; + + string_list_add_item(&sdirs,direntp->d_name); + } + } + closedir(dirStructP); + } + + sprintf(path,"%s/%s",DATA_PREFIX,rel_path); + if((dirStructP = opendir(path)) != NULL) + { + while((direntp = readdir(dirStructP)) != NULL) + { + char absolute_filename[1024]; + struct stat buf; + + sprintf(absolute_filename, "%s/%s", path, direntp->d_name); + + if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode)) + { + if(exception_str != NULL) + { + if(strstr(direntp->d_name,exception_str) != NULL) + continue; + } + if(glob != NULL) + if(strstr(direntp->d_name,glob) == NULL) + continue; + + string_list_add_item(&sdirs,direntp->d_name); + } + } + closedir(dirStructP); + } + + return sdirs; +} + +void free_strings(char **strings, int num) +{ + int i; + for(i=0; i < num; ++i) + free(strings[i]); +} + +/* --- SETUP --- */ +/* Set SuperTux configuration and save directories */ +void st_directory_setup(void) +{ + char *home; + char str[1024]; + /* Get home directory (from $HOME variable)... if we can't determine it, + use the current directory ("."): */ + if (getenv("HOME") != NULL) + home = getenv("HOME"); + else + home = "."; + + st_dir = (char *) malloc(sizeof(char) * (strlen(home) + + strlen("/.supertux") + 1)); + strcpy(st_dir, home); + strcat(st_dir, "/.supertux"); + + /* Remove .supertux config-file from old SuperTux versions */ + if(faccessible(st_dir)) + { + remove + (st_dir); + } + + st_save_dir = (char *) malloc(sizeof(char) * (strlen(st_dir) + strlen("/save") + 1)); + + strcpy(st_save_dir,st_dir); + strcat(st_save_dir,"/save"); + + /* Create them. In the case they exist they won't destroy anything. */ +#ifdef LINUX + + mkdir(st_dir, 0755); + mkdir(st_save_dir, 0755); + + sprintf(str, "%s/levels", st_dir); + mkdir(str, 0755); +#else + #ifdef WIN32 + + mkdir(st_dir); + mkdir(st_save_dir); + sprintf(str, "%s/levels", st_dir); + mkdir(str); +#endif +#endif + +} + +/* Create and setup menus. */ +void st_menu(void) +{ + menu_init(&main_menu); + menu_additem(&main_menu,menu_item_create(MN_LABEL,"Main Menu",0,0)); + menu_additem(&main_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&main_menu,menu_item_create(MN_ACTION,"Start Game",0,0)); + menu_additem(&main_menu,menu_item_create(MN_GOTO,"Load Game",0,&load_game_menu)); + menu_additem(&main_menu,menu_item_create(MN_GOTO,"Options",0,&options_menu)); + menu_additem(&main_menu,menu_item_create(MN_ACTION,"Level editor",0,0)); + menu_additem(&main_menu,menu_item_create(MN_ACTION,"Credits",0,0)); + menu_additem(&main_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&main_menu,menu_item_create(MN_ACTION,"Quit",0,0)); + + menu_init(&options_menu); + menu_additem(&options_menu,menu_item_create(MN_LABEL,"Options",0,0)); + menu_additem(&options_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Fullscreen",use_fullscreen,0)); + if(audio_device == YES) + { + menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Sound ",use_sound,0)); + menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Music ",use_music,0)); + } + else + { + menu_additem(&options_menu,menu_item_create(MN_DEACTIVE,"Sound ",use_sound,0)); + menu_additem(&options_menu,menu_item_create(MN_DEACTIVE,"Music ",use_music,0)); + } + menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Show FPS ",show_fps,0)); + menu_additem(&options_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&options_menu,menu_item_create(MN_BACK,"Back",0,0)); + + menu_init(&load_game_menu); + menu_additem(&load_game_menu,menu_item_create(MN_LABEL,"Load Game",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 1",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 2",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 3",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 4",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 5",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&load_game_menu,menu_item_create(MN_BACK,"Back",0,0)); + + menu_init(&save_game_menu); + menu_additem(&save_game_menu,menu_item_create(MN_LABEL,"Save Game",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 1",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 2",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 3",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 4",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 5",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&save_game_menu,menu_item_create(MN_BACK,"Back",0,0)); + + menu_init(&game_menu); + menu_additem(&game_menu,menu_item_create(MN_LABEL,"InGame Menu",0,0)); + menu_additem(&game_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&game_menu,menu_item_create(MN_ACTION,"Return To Game",0,0)); + menu_additem(&game_menu,menu_item_create(MN_GOTO,"Save Game",0,&save_game_menu)); + menu_additem(&game_menu,menu_item_create(MN_GOTO,"Load Game",0,&load_game_menu)); + menu_additem(&game_menu,menu_item_create(MN_GOTO,"Options",0,&options_menu)); + menu_additem(&game_menu,menu_item_create(MN_HL,"",0,0)); + menu_additem(&game_menu,menu_item_create(MN_ACTION,"Quit Game",0,0)); + + menu_init(&highscore_menu); + menu_additem(&highscore_menu,menu_item_create(MN_TEXTFIELD,"Enter your name:",0,0)); + +} + +void update_load_save_game_menu(menu_type* pmenu, int load) +{ + int i; + + for(i = 2; i < 7; ++i) + { + char *tmp; + slotinfo(&tmp,i-1); + if(load && strlen(tmp) == strlen("Slot X - Free") ) + pmenu->item[i].kind = MN_DEACTIVE; + else + pmenu->item[i].kind = MN_ACTION; + menu_item_change_text(&pmenu->item[i],tmp); + free(tmp); + } +} + +void process_save_load_game_menu(int save) +{ + int slot; + switch (slot = menu_check(save ? &save_game_menu : &load_game_menu)) + { + default: + if(slot != -1) + { + if(save == YES) + { + savegame(slot - 1); + } + else + { + if(game_started == NO) + { + gameloop("default",slot - 1,ST_GL_LOAD_GAME); + show_menu = YES; + menu_set_current(&main_menu); + } + else + loadgame(slot - 1); + } + st_pause_ticks_stop(); + } + break; + } +} + +/* Handle changes made to global settings in the options menu. */ +void process_options_menu(void) +{ + switch (menu_check(&options_menu)) + { + case 2: + if(use_fullscreen != options_menu.item[2].toggled) + { + use_fullscreen = !use_fullscreen; + st_video_setup(); + } + break; + case 3: + if(use_sound != options_menu.item[3].toggled) + use_sound = !use_sound; + break; + case 4: + if(use_music != options_menu.item[4].toggled) + { + if(use_music == YES) + { + if(playing_music()) + { + halt_music(); + } + use_music = NO; + } + else + { + use_music = YES; + if (!playing_music()) + { + play_current_music(); + } + } + } + break; + case 5: + if(show_fps != options_menu.item[5].toggled) + show_fps = !show_fps; + break; + } +} + +void st_general_setup(void) +{ + /* Seed random number generator: */ + + srand(SDL_GetTicks()); + + /* Set icon image: */ + + seticon(); + + /* Unicode needed for input handling: */ + + SDL_EnableUNICODE(1); + + /* Load global images: */ + + text_load(&black_text,DATA_PREFIX "/images/status/letters-black.png", TEXT_TEXT, 16,18); + text_load(&gold_text,DATA_PREFIX "/images/status/letters-gold.png", TEXT_TEXT, 16,18); + text_load(&blue_text,DATA_PREFIX "/images/status/letters-blue.png", TEXT_TEXT, 16,18); + text_load(&red_text,DATA_PREFIX "/images/status/letters-red.png", TEXT_TEXT, 16,18); + text_load(&white_text,DATA_PREFIX "/images/status/letters-white.png", TEXT_TEXT, 16,18); + text_load(&white_small_text,DATA_PREFIX "/images/status/letters-white-small.png", TEXT_TEXT, 8,9); + text_load(&white_big_text,DATA_PREFIX "/images/status/letters-white-big.png", TEXT_TEXT, 20,23); + text_load(&yellow_nums,DATA_PREFIX "/images/status/numbers.png", TEXT_NUM, 32,32); + + /* Load GUI/menu images: */ + texture_load(&checkbox, DATA_PREFIX "/images/status/checkbox.png", USE_ALPHA); + texture_load(&checkbox_checked, DATA_PREFIX "/images/status/checkbox-checked.png", USE_ALPHA); + texture_load(&back, DATA_PREFIX "/images/status/back.png", USE_ALPHA); + texture_load(&arrow_left, DATA_PREFIX "/images/icons/left.png", USE_ALPHA); + texture_load(&arrow_right, DATA_PREFIX "/images/icons/right.png", USE_ALPHA); + +} + +void st_general_free(void) +{ + + /* Free global images: */ + + text_free(&black_text); + text_free(&gold_text); + text_free(&white_text); + text_free(&blue_text); + text_free(&red_text); + text_free(&white_small_text); + text_free(&white_big_text); + + /* Free GUI/menu images: */ + texture_free(&checkbox); + texture_free(&checkbox_checked); + texture_free(&back); + texture_free(&arrow_left); + texture_free(&arrow_right); + + /* Free menus */ + + menu_free(&main_menu); + menu_free(&game_menu); + menu_free(&options_menu); + menu_free(&highscore_menu); + menu_free(&save_game_menu); + menu_free(&load_game_menu); + +} + +void st_video_setup(void) +{ + + if(screen != NULL) + SDL_FreeSurface(screen); + + /* Init SDL Video: */ + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + fprintf(stderr, + "\nError: I could not initialize video!\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + exit(1); + } + + /* Open display: */ + + if(use_gl) + st_video_setup_gl(); + else + st_video_setup_sdl(); + + texture_setup(); + + /* Set window manager stuff: */ + + SDL_WM_SetCaption("Super Tux", "Super Tux"); + +} + +void st_video_setup_sdl(void) +{ + SDL_FreeSurface(screen); + + if (use_fullscreen == YES) + { + screen = SDL_SetVideoMode(640, 480, 0, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */ + if (screen == NULL) + { + fprintf(stderr, + "\nWarning: I could not set up fullscreen video for " + "640x480 mode.\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + use_fullscreen = NO; + } + } + else + { + screen = SDL_SetVideoMode(640, 480, 0, SDL_HWSURFACE | SDL_DOUBLEBUF ); + + if (screen == NULL) + { + fprintf(stderr, + "\nError: I could not set up video for 640x480 mode.\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + exit(1); + } + } +} + +void st_video_setup_gl(void) +{ +#ifndef NOOPENGL + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + if (use_fullscreen == YES) + { + screen = SDL_SetVideoMode(640, 480, 0, SDL_FULLSCREEN | SDL_OPENGL) ; /* | SDL_HWSURFACE); */ + if (screen == NULL) + { + fprintf(stderr, + "\nWarning: I could not set up fullscreen video for " + "640x480 mode.\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + use_fullscreen = NO; + } + } + else + { + screen = SDL_SetVideoMode(640, 480, 0, SDL_OPENGL); + + if (screen == NULL) + { + fprintf(stderr, + "\nError: I could not set up video for 640x480 mode.\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + exit(1); + } + } + + /* + * Set up OpenGL for 2D rendering. + */ + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + glViewport(0, 0, screen->w, screen->h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, 0.0f); + +#endif + +} + +void st_joystick_setup(void) +{ + + /* Init Joystick: */ + +#ifdef JOY_YES + use_joystick = YES; + + if (SDL_Init(SDL_INIT_JOYSTICK) < 0) + { + fprintf(stderr, "Warning: I could not initialize joystick!\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + + use_joystick = NO; + } + else + { + /* Open joystick: */ + + if (SDL_NumJoysticks() <= 0) + { + fprintf(stderr, "Warning: No joysticks are available.\n"); + + use_joystick = NO; + } + else + { + js = SDL_JoystickOpen(0); + + if (js == NULL) + { + fprintf(stderr, "Warning: Could not open joystick 1.\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + + use_joystick = NO; + } + else + { + /* Check for proper joystick configuration: */ + + if (SDL_JoystickNumAxes(js) < 2) + { + fprintf(stderr, + "Warning: Joystick does not have enough axes!\n"); + + use_joystick = NO; + } + else + { + if (SDL_JoystickNumButtons(js) < 2) + { + fprintf(stderr, + "Warning: " + "Joystick does not have enough buttons!\n"); + + use_joystick = NO; + } + } + } + } + } +#endif + +} + +void st_audio_setup(void) +{ + + /* Init SDL Audio silently even if --disable-sound : */ + + if (audio_device == YES) + { + if (SDL_Init(SDL_INIT_AUDIO) < 0) + { + /* only print out message if sound or music + was not disabled at command-line + */ + if (use_sound == YES || use_music == YES) + { + fprintf(stderr, + "\nWarning: I could not initialize audio!\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + } + /* keep the programming logic the same :-) + because in this case, use_sound & use_music' values are ignored + when there's no available audio device + */ + use_sound = NO; + use_music = NO; + audio_device = NO; + } + } + + + /* Open sound silently regarless the value of "use_sound": */ + + if (audio_device == YES) + { + if (open_audio(44100, AUDIO_S16, 2, 2048) < 0) + { + /* only print out message if sound or music + was not disabled at command-line + */ + if ((use_sound == YES) || (use_music == YES)) + { + fprintf(stderr, + "\nWarning: I could not set up audio for 44100 Hz " + "16-bit stereo.\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", SDL_GetError()); + } + use_sound = NO; + use_music = NO; + audio_device = NO; + } + } + +} + + +/* --- SHUTDOWN --- */ + +void st_shutdown(void) +{ + close_audio(); + SDL_Quit(); +} + + +/* --- ABORT! --- */ + +void st_abort(char * reason, char * details) +{ + fprintf(stderr, "\nError: %s\n%s\n\n", reason, details); + st_shutdown(); + exit(1); +} + + +/* Set Icon (private) */ + +void seticon(void) +{ + int masklen; + Uint8 * mask; + SDL_Surface * icon; + + + /* Load icon into a surface: */ + + icon = IMG_Load(DATA_PREFIX "/images/icon.png"); + if (icon == NULL) + { + fprintf(stderr, + "\nError: I could not load the icon image: %s\n" + "The Simple DirectMedia error that occured was:\n" + "%s\n\n", DATA_PREFIX "/images/icon.png", SDL_GetError()); + exit(1); + } + + + /* Create mask: */ + + masklen = (((icon -> w) + 7) / 8) * (icon -> h); + mask = (Uint8*) malloc(masklen * sizeof(Uint8)); + memset(mask, 0xFF, masklen); + + + /* Set icon: */ + + SDL_WM_SetIcon(icon, mask); + + + /* Free icon surface & mask: */ + + free(mask); + SDL_FreeSurface(icon); +} + + +/* Parse command-line arguments: */ + +void parseargs(int argc, char * argv[]) +{ + int i; + + /* Set defaults: */ + + + debug_mode = NO; + use_fullscreen = NO; + show_fps = NO; + use_gl = NO; + +#ifndef NOSOUND + + use_sound = YES; + use_music = YES; + audio_device = YES; +#else + + use_sound = NO; + use_music = NO; + audio_device = NO; +#endif + + /* Parse arguments: */ + + for (i = 1; i < argc; i++) + { + if (strcmp(argv[i], "--fullscreen") == 0 || + strcmp(argv[i], "-f") == 0) + { + /* Use full screen: */ + + use_fullscreen = YES; + } + else if (strcmp(argv[i], "--show-fps") == 0) + { + /* Use full screen: */ + + show_fps = YES; + } + else if (strcmp(argv[i], "--opengl") == 0 || + strcmp(argv[i], "-gl") == 0) + { +#ifndef NOOPENGL + /* Use OpengGL: */ + + use_gl = YES; +#endif + + } + else if (strcmp(argv[i], "--usage") == 0) + { + /* Show usage: */ + + usage(argv[0], 0); + } + else if (strcmp(argv[i], "--version") == 0) + { + /* Show version: */ + + printf("Super Tux - version " VERSION "\n"); + exit(0); + } + else if (strcmp(argv[i], "--disable-sound") == 0) + { + /* Disable the compiled in sound feature */ +#ifndef NOSOUND + printf("Sounds disabled \n"); + use_sound = NO; +#else + + printf("Warning: Sound capability has not been compiled into this build.\n"); +#endif + + } + else if (strcmp(argv[i], "--disable-music") == 0) + { + /* Disable the compiled in sound feature */ +#ifndef NOSOUND + printf("Music disabled \n"); + use_music = NO; +#else + + printf("Warning: Music feature is not compiled in \n"); +#endif + + } + else if (strcmp(argv[i], "--debug-mode") == 0) + { + /* Enable the debug-mode */ + debug_mode = YES; + + } + else if (strcmp(argv[i], "--help") == 0) + { /* Show help: */ + + printf("Super Tux " VERSION "\n\n"); + + printf("---------- Command-line options ----------\n\n"); + + printf(" --opengl - If opengl support was compiled in, this will enable the EXPERIMENTAL OpenGL mode.\n\n"); + + printf(" --disable-sound - If sound support was compiled in, this will\n disable sound for this session of the game.\n\n"); + + printf(" --disable-music - Like above, but this will disable music.\n\n"); + + printf(" --fullscreen - Run in fullscreen mode.\n\n"); + + printf(" --debug-mode - Enables the debug-mode, which is useful for developers.\n\n"); + + printf(" --help - Display a help message summarizing command-line\n options, license and game controls.\n\n"); + + printf(" --usage - Display a brief message summarizing command-line options.\n\n"); + + printf(" --version - Display the version of SuperTux you're running.\n\n\n"); + + + printf("---------- License ----------\n\n"); + printf(" This program comes with ABSOLUTELY NO WARRANTY.\n"); + printf(" This is free software, and you are welcome to redistribute\n"); + printf(" or modify it under certain conditions. See the file \n"); + printf(" \"COPYING.txt\" for more details.\n\n\n"); + + printf("---------- Game controls ----------\n\n"); + printf(" Please see the file \"README.txt\"\n\n"); + + exit(0); + } + else + { + /* Unknown - complain! */ + + usage(argv[0], 1); + } + } +} + + +/* Display usage: */ + +void usage(char * prog, int ret) +{ + FILE * fi; + + + /* Determine which stream to write to: */ + + if (ret == 0) + fi = stdout; + else + fi = stderr; + + + /* Display the usage message: */ + + fprintf(fi, "Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug-mode] | [--usage | --help | --version]\n", + prog); + + + /* Quit! */ + + exit(ret); +} + diff --git a/src/sound.c b/src/sound.c deleted file mode 100644 index 172148f6d..000000000 --- a/src/sound.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - sound.c - - Super Tux - Audio Functions - - by Bill Kendrick - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 22, 2000 - March 15, 2004 -*/ - -#include "defines.h" -#include "globals.h" -#include "sound.h" -#include "setup.h" - -/*global variable*/ -int use_sound; /* handle sound on/off menu and command-line option */ -int use_music; /* handle music on/off menu and command-line option */ -int audio_device; /* != 0: available and initialized */ -int current_music; - -char * soundfilenames[NUM_SOUNDS] = { - DATA_PREFIX "/sounds/jump.wav", - DATA_PREFIX "/sounds/bigjump.wav", - DATA_PREFIX "/sounds/skid.wav", - DATA_PREFIX "/sounds/distro.wav", - DATA_PREFIX "/sounds/herring.wav", - DATA_PREFIX "/sounds/brick.wav", - DATA_PREFIX "/sounds/hurt.wav", - DATA_PREFIX "/sounds/squish.wav", - DATA_PREFIX "/sounds/fall.wav", - DATA_PREFIX "/sounds/ricochet.wav", - DATA_PREFIX "/sounds/bump-upgrade.wav", - DATA_PREFIX "/sounds/upgrade.wav", - DATA_PREFIX "/sounds/excellent.wav", - DATA_PREFIX "/sounds/coffee.wav", - DATA_PREFIX "/sounds/shoot.wav", - DATA_PREFIX "/sounds/lifeup.wav", - DATA_PREFIX "/sounds/stomp.wav", - DATA_PREFIX "/sounds/kick.wav" - }; - - -#ifndef NOSOUND - -#include - -Mix_Chunk * sounds[NUM_SOUNDS]; -Mix_Music * level_song, * level_song_fast, * herring_song; - -/* --- OPEN THE AUDIO DEVICE --- */ - -int open_audio (int frequency, Uint16 format, int channels, int chunksize) -{ - /* if success we reserved some channels and register panning effects */ - if (Mix_OpenAudio( frequency, format, channels, chunksize ) == 0) - { - if (Mix_ReserveChannels( SOUND_RESERVED_CHANNELS ) - != SOUND_RESERVED_CHANNELS ) - { - DEBUG_MSG( "Warning: open_audio could'nt reserve channels" ); - } - - /* prepare the spanning effects, no error checking */ - Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 ); - Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 ); - return 0; - } - else - { - return -1; - } -} - - -/* --- CLOSE THE AUDIO DEVICE --- */ - -void close_audio( void ) -{ - if (audio_device == YES) { - Mix_UnregisterAllEffects( SOUND_LEFT_SPEAKER ); - Mix_UnregisterAllEffects( SOUND_RIGHT_SPEAKER ); - Mix_CloseAudio(); - } -} - - -/* --- LOAD A SOUND --- */ - -Mix_Chunk * load_sound(char * file) -{ - Mix_Chunk * snd; - - snd = Mix_LoadWAV(file); - - /* printf message and abort if there is an initialized audio device */ - if ((snd == NULL) && (audio_device == YES)) - st_abort("Can't load", file); - - return(snd); -} - - -/* --- LOAD A SONG --- */ - -Mix_Music * load_song(char * file) -{ - Mix_Music * sng; - - sng = Mix_LoadMUS(file); - - /* printf message and abort if there is an initialized audio device */ - if ((sng == NULL) && (audio_device == YES)) - st_abort("Can't load", file); - return (sng); -} - - -/* --- PLAY A SOUND ON LEFT OR RIGHT OR CENTER SPEAKER --- */ - -void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker) -{ - /* this won't call the function if the user has disabled sound - * either via menu or via command-line option - */ - if ((use_sound == YES) && (audio_device == YES)) - { - Mix_PlayChannel( whichSpeaker, snd, 0); - - /* prepare for panning effects for next call */ - /* warning: currently, I do not check for errors here */ - switch (whichSpeaker) { - case SOUND_LEFT_SPEAKER: - Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 ); - break; - case SOUND_RIGHT_SPEAKER: - Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 ); - break; - default: // keep the compiler happy - break; - } - } -} - - -void free_chunk(Mix_Chunk *chunk) -{ - if (chunk != NULL) - { - DEBUG_MSG( __PRETTY_FUNCTION__ ); - Mix_FreeChunk( chunk ); - chunk = NULL; - } -} - - -int playing_music(void) -{ - if (use_music == YES) - { - return Mix_PlayingMusic(); - } - else - { - /* we are in --disable-music we can't be playing music */ - return 0; - } -} - - -int halt_music(void) -{ - if ((use_music == YES) && (audio_device == YES)) - { - return Mix_HaltMusic(); - } - else - { - return 0; - } -} - - -int play_music(Mix_Music *music, int loops) -{ - if ((use_music == YES) && (audio_device == YES)) - { - DEBUG_MSG(__PRETTY_FUNCTION__); - return Mix_PlayMusic(music, loops); - } - else - { - /* return error since you're trying to play music in --disable-sound mode */ - return -1; - } -} - - -void free_music(Mix_Music *music) -{ - if ( music != NULL ) - { - DEBUG_MSG(__PRETTY_FUNCTION__); - Mix_FreeMusic( music ); - music = NULL; - } -} - int get_current_music() - { - return current_music; - } - - void set_current_music(int music) - { - current_music = music; - } - - void play_current_music() - { - if(playing_music()) - halt_music(); - - switch(current_music) - { - case LEVEL_MUSIC: - play_music(level_song, -1); // -1 to play forever - break; - case HERRING_MUSIC: - play_music(herring_song, -1); - break; - case HURRYUP_MUSIC: - play_music(level_song_fast, -1); - break; - case NO_MUSIC: // keep the compiler happy for the moment :-) - {} - /*default:*/ - } - /* use halt_music whenever you want to stop it */ -} - -#else - -void* sounds[NUM_SOUNDS]; -void* level_song, * level_song_fast, * herring_song; - -int open_audio (int frequency, int format, int channels, int chunksize) -{ - return -1; -} - - -void close_audio(void) -{} - - -void* load_sound(void* file) -{ - return NULL; -} - - -void play_sound(void * snd, enum Sound_Speaker whichSpeaker) -{} - - -void* load_song(void* file) -{ - return NULL; -} - - -int playing_music() -{ - return 0; -} - - -void halt_music() -{} - - -int play_music(void *music, int loops) -{ - return 0; -} - - -void free_music(void *music) -{} - - -void free_chunk(void *chunk) -{} - -int get_current_music() -{ -} - -void set_current_music(int music) -{ -} - -void play_current_music(void) -{} - -#endif diff --git a/src/sound.cpp b/src/sound.cpp new file mode 100644 index 000000000..172148f6d --- /dev/null +++ b/src/sound.cpp @@ -0,0 +1,308 @@ +/* + sound.c + + Super Tux - Audio Functions + + by Bill Kendrick + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 22, 2000 - March 15, 2004 +*/ + +#include "defines.h" +#include "globals.h" +#include "sound.h" +#include "setup.h" + +/*global variable*/ +int use_sound; /* handle sound on/off menu and command-line option */ +int use_music; /* handle music on/off menu and command-line option */ +int audio_device; /* != 0: available and initialized */ +int current_music; + +char * soundfilenames[NUM_SOUNDS] = { + DATA_PREFIX "/sounds/jump.wav", + DATA_PREFIX "/sounds/bigjump.wav", + DATA_PREFIX "/sounds/skid.wav", + DATA_PREFIX "/sounds/distro.wav", + DATA_PREFIX "/sounds/herring.wav", + DATA_PREFIX "/sounds/brick.wav", + DATA_PREFIX "/sounds/hurt.wav", + DATA_PREFIX "/sounds/squish.wav", + DATA_PREFIX "/sounds/fall.wav", + DATA_PREFIX "/sounds/ricochet.wav", + DATA_PREFIX "/sounds/bump-upgrade.wav", + DATA_PREFIX "/sounds/upgrade.wav", + DATA_PREFIX "/sounds/excellent.wav", + DATA_PREFIX "/sounds/coffee.wav", + DATA_PREFIX "/sounds/shoot.wav", + DATA_PREFIX "/sounds/lifeup.wav", + DATA_PREFIX "/sounds/stomp.wav", + DATA_PREFIX "/sounds/kick.wav" + }; + + +#ifndef NOSOUND + +#include + +Mix_Chunk * sounds[NUM_SOUNDS]; +Mix_Music * level_song, * level_song_fast, * herring_song; + +/* --- OPEN THE AUDIO DEVICE --- */ + +int open_audio (int frequency, Uint16 format, int channels, int chunksize) +{ + /* if success we reserved some channels and register panning effects */ + if (Mix_OpenAudio( frequency, format, channels, chunksize ) == 0) + { + if (Mix_ReserveChannels( SOUND_RESERVED_CHANNELS ) + != SOUND_RESERVED_CHANNELS ) + { + DEBUG_MSG( "Warning: open_audio could'nt reserve channels" ); + } + + /* prepare the spanning effects, no error checking */ + Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 ); + Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 ); + return 0; + } + else + { + return -1; + } +} + + +/* --- CLOSE THE AUDIO DEVICE --- */ + +void close_audio( void ) +{ + if (audio_device == YES) { + Mix_UnregisterAllEffects( SOUND_LEFT_SPEAKER ); + Mix_UnregisterAllEffects( SOUND_RIGHT_SPEAKER ); + Mix_CloseAudio(); + } +} + + +/* --- LOAD A SOUND --- */ + +Mix_Chunk * load_sound(char * file) +{ + Mix_Chunk * snd; + + snd = Mix_LoadWAV(file); + + /* printf message and abort if there is an initialized audio device */ + if ((snd == NULL) && (audio_device == YES)) + st_abort("Can't load", file); + + return(snd); +} + + +/* --- LOAD A SONG --- */ + +Mix_Music * load_song(char * file) +{ + Mix_Music * sng; + + sng = Mix_LoadMUS(file); + + /* printf message and abort if there is an initialized audio device */ + if ((sng == NULL) && (audio_device == YES)) + st_abort("Can't load", file); + return (sng); +} + + +/* --- PLAY A SOUND ON LEFT OR RIGHT OR CENTER SPEAKER --- */ + +void play_sound(Mix_Chunk * snd, enum Sound_Speaker whichSpeaker) +{ + /* this won't call the function if the user has disabled sound + * either via menu or via command-line option + */ + if ((use_sound == YES) && (audio_device == YES)) + { + Mix_PlayChannel( whichSpeaker, snd, 0); + + /* prepare for panning effects for next call */ + /* warning: currently, I do not check for errors here */ + switch (whichSpeaker) { + case SOUND_LEFT_SPEAKER: + Mix_SetPanning( SOUND_LEFT_SPEAKER, 230, 24 ); + break; + case SOUND_RIGHT_SPEAKER: + Mix_SetPanning( SOUND_RIGHT_SPEAKER, 24, 230 ); + break; + default: // keep the compiler happy + break; + } + } +} + + +void free_chunk(Mix_Chunk *chunk) +{ + if (chunk != NULL) + { + DEBUG_MSG( __PRETTY_FUNCTION__ ); + Mix_FreeChunk( chunk ); + chunk = NULL; + } +} + + +int playing_music(void) +{ + if (use_music == YES) + { + return Mix_PlayingMusic(); + } + else + { + /* we are in --disable-music we can't be playing music */ + return 0; + } +} + + +int halt_music(void) +{ + if ((use_music == YES) && (audio_device == YES)) + { + return Mix_HaltMusic(); + } + else + { + return 0; + } +} + + +int play_music(Mix_Music *music, int loops) +{ + if ((use_music == YES) && (audio_device == YES)) + { + DEBUG_MSG(__PRETTY_FUNCTION__); + return Mix_PlayMusic(music, loops); + } + else + { + /* return error since you're trying to play music in --disable-sound mode */ + return -1; + } +} + + +void free_music(Mix_Music *music) +{ + if ( music != NULL ) + { + DEBUG_MSG(__PRETTY_FUNCTION__); + Mix_FreeMusic( music ); + music = NULL; + } +} + int get_current_music() + { + return current_music; + } + + void set_current_music(int music) + { + current_music = music; + } + + void play_current_music() + { + if(playing_music()) + halt_music(); + + switch(current_music) + { + case LEVEL_MUSIC: + play_music(level_song, -1); // -1 to play forever + break; + case HERRING_MUSIC: + play_music(herring_song, -1); + break; + case HURRYUP_MUSIC: + play_music(level_song_fast, -1); + break; + case NO_MUSIC: // keep the compiler happy for the moment :-) + {} + /*default:*/ + } + /* use halt_music whenever you want to stop it */ +} + +#else + +void* sounds[NUM_SOUNDS]; +void* level_song, * level_song_fast, * herring_song; + +int open_audio (int frequency, int format, int channels, int chunksize) +{ + return -1; +} + + +void close_audio(void) +{} + + +void* load_sound(void* file) +{ + return NULL; +} + + +void play_sound(void * snd, enum Sound_Speaker whichSpeaker) +{} + + +void* load_song(void* file) +{ + return NULL; +} + + +int playing_music() +{ + return 0; +} + + +void halt_music() +{} + + +int play_music(void *music, int loops) +{ + return 0; +} + + +void free_music(void *music) +{} + + +void free_chunk(void *chunk) +{} + +int get_current_music() +{ +} + +void set_current_music(int music) +{ +} + +void play_current_music(void) +{} + +#endif diff --git a/src/special.c b/src/special.c deleted file mode 100644 index 8121f7e62..000000000 --- a/src/special.c +++ /dev/null @@ -1,284 +0,0 @@ -// -// C Implementation: special -// -// Description: -// -// -// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "SDL.h" -#include "defines.h" -#include "special.h" -#include "gameloop.h" -#include "screen.h" -#include "sound.h" -#include "scene.h" -#include "globals.h" -#include "player.h" - -texture_type img_bullet; -texture_type img_golden_herring; -bitmask* bm_bullet; - -void create_special_bitmasks() -{ - bm_bullet = bitmask_create_SDL(img_bullet.sdl_surface); -} - -void bullet_init(bullet_type* pbullet, float x, float y, float xm, int dir) -{ - pbullet->base.width = 4; - pbullet->base.height = 4; - pbullet->base.alive = YES; - - if (dir == RIGHT) - { - pbullet->base.x = x + 32; - pbullet->base.xm = BULLET_XM + xm; - } - else - { - pbullet->base.x = x; - pbullet->base.xm = -BULLET_XM + xm; - } - - pbullet->base.y = y; - pbullet->base.ym = BULLET_STARTING_YM; - pbullet->old_base = pbullet->base; -} - -void bullet_action(bullet_type* pbullet) -{ - if (pbullet->base.alive) - { - pbullet->base.x = pbullet->base.x + pbullet->base.xm * frame_ratio; - pbullet->base.y = pbullet->base.y + pbullet->base.ym * frame_ratio; - - collision_swept_object_map(&pbullet->old_base,&pbullet->base); - - if (issolid(pbullet->base.x, pbullet->base.y + 4) || issolid(pbullet->base.x, pbullet->base.y)) - { - pbullet->base.ym = -pbullet->base.ym; - pbullet->base.y = (int)(pbullet->base.y / 32) * 32; - } - - pbullet->base.ym = pbullet->base.ym + GRAVITY; - - if (pbullet->base.x < scroll_x || - pbullet->base.x > scroll_x + screen->w || - pbullet->base.y < 0 || - pbullet->base.y > screen->h || - issolid(pbullet->base.x + 4, pbullet->base.y + 2) || - issolid(pbullet->base.x, pbullet->base.y + 2)) - { - pbullet->base.alive = NO; - } - } - -} - -void bullet_draw(bullet_type* pbullet) -{ - if (pbullet->base.alive && - pbullet->base.x >= scroll_x - pbullet->base.width && - pbullet->base.x <= scroll_x + screen->w) - { - texture_draw(&img_bullet, pbullet->base.x - scroll_x, pbullet->base.y, - NO_UPDATE); - } -} - -void bullet_collision(bullet_type* pbullet, int c_object) -{ - - if(c_object == CO_BADGUY) - pbullet->base.alive = NO; - -} - -void upgrade_init(upgrade_type *pupgrade, float x, float y, int dir, int kind) -{ - pupgrade->base.width = 32; - pupgrade->base.height = 0; - pupgrade->base.alive = YES; - pupgrade->kind = kind; - pupgrade->base.x = x; - pupgrade->base.y = y; - if(dir == LEFT) - pupgrade->base.xm = -2; - else - pupgrade->base.xm = 2; - pupgrade->base.ym = -2; - pupgrade->base.height = 0; - pupgrade->old_base = pupgrade->base; -} - -void upgrade_action(upgrade_type *pupgrade) -{ - - if (pupgrade->base.alive) - { - if (pupgrade->base.height < 32) - { - /* Rise up! */ - - pupgrade->base.height = pupgrade->base.height + 0.7 * frame_ratio; - if(pupgrade->base.height > 32) - pupgrade->base.height = 32; - } - else - { - /* Move around? */ - - if (pupgrade->kind == UPGRADE_MINTS || - pupgrade->kind == UPGRADE_HERRING) - { - pupgrade->base.x = pupgrade->base.x + pupgrade->base.xm * frame_ratio; - pupgrade->base.y = pupgrade->base.y + pupgrade->base.ym * frame_ratio; - - collision_swept_object_map(&pupgrade->old_base,&pupgrade->base); - - /* Off the screen? Kill it! */ - - if (pupgrade->base.x < scroll_x - pupgrade->base.width) - pupgrade->base.alive = NO; - if (pupgrade->base.y > screen->h) - pupgrade->base.alive = NO; - - if (issolid(pupgrade->base.x + 1, pupgrade->base.y + 32.) || - issolid(pupgrade->base.x + 31., pupgrade->base.y + 32.)) - { - if (pupgrade->base.ym > 0) - { - if (pupgrade->kind == UPGRADE_MINTS) - { - pupgrade->base.ym = 0; - } - else if (pupgrade->kind == UPGRADE_HERRING) - { - pupgrade->base.ym = -8; - } - - pupgrade->base.y = (int)(pupgrade->base.y / 32) * 32; - } - } - else - pupgrade->base.ym = pupgrade->base.ym + GRAVITY * frame_ratio; - - if (issolid(pupgrade->base.x - 1, (int) pupgrade->base.y)) - { - if(pupgrade->base.xm < 0) - pupgrade->base.xm = -pupgrade->base.xm; - } - else if (issolid(pupgrade->base.x + pupgrade->base.width, (int) pupgrade->base.y)) - { - if(pupgrade->base.xm > 0) - pupgrade->base.xm = -pupgrade->base.xm; - } - } - - } - } -} - -void upgrade_draw(upgrade_type* pupgrade) -{ - SDL_Rect dest; - if (pupgrade->base.alive) - { - if (pupgrade->base.height < 32) - { - /* Rising up... */ - - dest.x = (int)(pupgrade->base.x - scroll_x); - dest.y = (int)(pupgrade->base.y + 32 - pupgrade->base.height); - dest.w = 32; - dest.h = (int)pupgrade->base.height; - - if (pupgrade->kind == UPGRADE_MINTS) - texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); - else if (pupgrade->kind == UPGRADE_COFFEE) - texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); - else if (pupgrade->kind == UPGRADE_HERRING) - texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); - } - else - { - if (pupgrade->kind == UPGRADE_MINTS) - { - texture_draw(&img_mints, - pupgrade->base.x - scroll_x, pupgrade->base.y, - NO_UPDATE); - } - else if (pupgrade->kind == UPGRADE_COFFEE) - { - texture_draw(&img_coffee, - pupgrade->base.x - scroll_x, pupgrade->base.y, - NO_UPDATE); - } - else if (pupgrade->kind == UPGRADE_HERRING) - { - texture_draw(&img_golden_herring, - pupgrade->base.x - scroll_x, pupgrade->base.y, - NO_UPDATE); - } - } - } -} - -void upgrade_collision(upgrade_type* pupgrade, void* p_c_object, int c_object) -{ - player_type* pplayer = NULL; - - switch (c_object) - { - case CO_PLAYER: - /* Remove the upgrade: */ - - /* p_c_object is CO_PLAYER, so assign it to pplayer */ - pplayer = (player_type*) p_c_object; - - pupgrade->base.alive = NO; - - /* Affect the player: */ - - if (pupgrade->kind == UPGRADE_MINTS) - { - play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER); - pplayer->size = BIG; - pplayer->base.height = 64; - pplayer->base.y -= 32; - if(collision_object_map(&pplayer->base)) - { - pplayer->base.height = 32; - pplayer->base.y += 32; - pplayer->duck = YES; - } - timer_start(&super_bkgd_timer, 350); - } - else if (pupgrade->kind == UPGRADE_COFFEE) - { - play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER); - pplayer->got_coffee = YES; - timer_start(&super_bkgd_timer, 250); - } - else if (pupgrade->kind == UPGRADE_HERRING) - { - play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER); - timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME); - timer_start(&super_bkgd_timer, 250); - /* play the herring song ^^ */ - if (get_current_music() != HURRYUP_MUSIC) - { - set_current_music(HERRING_MUSIC); - play_current_music(); - } - } - break; - } -} - diff --git a/src/special.cpp b/src/special.cpp new file mode 100644 index 000000000..8121f7e62 --- /dev/null +++ b/src/special.cpp @@ -0,0 +1,284 @@ +// +// C Implementation: special +// +// Description: +// +// +// Author: Tobias Glaesser & Bill Kendrick, (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "SDL.h" +#include "defines.h" +#include "special.h" +#include "gameloop.h" +#include "screen.h" +#include "sound.h" +#include "scene.h" +#include "globals.h" +#include "player.h" + +texture_type img_bullet; +texture_type img_golden_herring; +bitmask* bm_bullet; + +void create_special_bitmasks() +{ + bm_bullet = bitmask_create_SDL(img_bullet.sdl_surface); +} + +void bullet_init(bullet_type* pbullet, float x, float y, float xm, int dir) +{ + pbullet->base.width = 4; + pbullet->base.height = 4; + pbullet->base.alive = YES; + + if (dir == RIGHT) + { + pbullet->base.x = x + 32; + pbullet->base.xm = BULLET_XM + xm; + } + else + { + pbullet->base.x = x; + pbullet->base.xm = -BULLET_XM + xm; + } + + pbullet->base.y = y; + pbullet->base.ym = BULLET_STARTING_YM; + pbullet->old_base = pbullet->base; +} + +void bullet_action(bullet_type* pbullet) +{ + if (pbullet->base.alive) + { + pbullet->base.x = pbullet->base.x + pbullet->base.xm * frame_ratio; + pbullet->base.y = pbullet->base.y + pbullet->base.ym * frame_ratio; + + collision_swept_object_map(&pbullet->old_base,&pbullet->base); + + if (issolid(pbullet->base.x, pbullet->base.y + 4) || issolid(pbullet->base.x, pbullet->base.y)) + { + pbullet->base.ym = -pbullet->base.ym; + pbullet->base.y = (int)(pbullet->base.y / 32) * 32; + } + + pbullet->base.ym = pbullet->base.ym + GRAVITY; + + if (pbullet->base.x < scroll_x || + pbullet->base.x > scroll_x + screen->w || + pbullet->base.y < 0 || + pbullet->base.y > screen->h || + issolid(pbullet->base.x + 4, pbullet->base.y + 2) || + issolid(pbullet->base.x, pbullet->base.y + 2)) + { + pbullet->base.alive = NO; + } + } + +} + +void bullet_draw(bullet_type* pbullet) +{ + if (pbullet->base.alive && + pbullet->base.x >= scroll_x - pbullet->base.width && + pbullet->base.x <= scroll_x + screen->w) + { + texture_draw(&img_bullet, pbullet->base.x - scroll_x, pbullet->base.y, + NO_UPDATE); + } +} + +void bullet_collision(bullet_type* pbullet, int c_object) +{ + + if(c_object == CO_BADGUY) + pbullet->base.alive = NO; + +} + +void upgrade_init(upgrade_type *pupgrade, float x, float y, int dir, int kind) +{ + pupgrade->base.width = 32; + pupgrade->base.height = 0; + pupgrade->base.alive = YES; + pupgrade->kind = kind; + pupgrade->base.x = x; + pupgrade->base.y = y; + if(dir == LEFT) + pupgrade->base.xm = -2; + else + pupgrade->base.xm = 2; + pupgrade->base.ym = -2; + pupgrade->base.height = 0; + pupgrade->old_base = pupgrade->base; +} + +void upgrade_action(upgrade_type *pupgrade) +{ + + if (pupgrade->base.alive) + { + if (pupgrade->base.height < 32) + { + /* Rise up! */ + + pupgrade->base.height = pupgrade->base.height + 0.7 * frame_ratio; + if(pupgrade->base.height > 32) + pupgrade->base.height = 32; + } + else + { + /* Move around? */ + + if (pupgrade->kind == UPGRADE_MINTS || + pupgrade->kind == UPGRADE_HERRING) + { + pupgrade->base.x = pupgrade->base.x + pupgrade->base.xm * frame_ratio; + pupgrade->base.y = pupgrade->base.y + pupgrade->base.ym * frame_ratio; + + collision_swept_object_map(&pupgrade->old_base,&pupgrade->base); + + /* Off the screen? Kill it! */ + + if (pupgrade->base.x < scroll_x - pupgrade->base.width) + pupgrade->base.alive = NO; + if (pupgrade->base.y > screen->h) + pupgrade->base.alive = NO; + + if (issolid(pupgrade->base.x + 1, pupgrade->base.y + 32.) || + issolid(pupgrade->base.x + 31., pupgrade->base.y + 32.)) + { + if (pupgrade->base.ym > 0) + { + if (pupgrade->kind == UPGRADE_MINTS) + { + pupgrade->base.ym = 0; + } + else if (pupgrade->kind == UPGRADE_HERRING) + { + pupgrade->base.ym = -8; + } + + pupgrade->base.y = (int)(pupgrade->base.y / 32) * 32; + } + } + else + pupgrade->base.ym = pupgrade->base.ym + GRAVITY * frame_ratio; + + if (issolid(pupgrade->base.x - 1, (int) pupgrade->base.y)) + { + if(pupgrade->base.xm < 0) + pupgrade->base.xm = -pupgrade->base.xm; + } + else if (issolid(pupgrade->base.x + pupgrade->base.width, (int) pupgrade->base.y)) + { + if(pupgrade->base.xm > 0) + pupgrade->base.xm = -pupgrade->base.xm; + } + } + + } + } +} + +void upgrade_draw(upgrade_type* pupgrade) +{ + SDL_Rect dest; + if (pupgrade->base.alive) + { + if (pupgrade->base.height < 32) + { + /* Rising up... */ + + dest.x = (int)(pupgrade->base.x - scroll_x); + dest.y = (int)(pupgrade->base.y + 32 - pupgrade->base.height); + dest.w = 32; + dest.h = (int)pupgrade->base.height; + + if (pupgrade->kind == UPGRADE_MINTS) + texture_draw_part(&img_mints,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); + else if (pupgrade->kind == UPGRADE_COFFEE) + texture_draw_part(&img_coffee,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); + else if (pupgrade->kind == UPGRADE_HERRING) + texture_draw_part(&img_golden_herring,0,0,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); + } + else + { + if (pupgrade->kind == UPGRADE_MINTS) + { + texture_draw(&img_mints, + pupgrade->base.x - scroll_x, pupgrade->base.y, + NO_UPDATE); + } + else if (pupgrade->kind == UPGRADE_COFFEE) + { + texture_draw(&img_coffee, + pupgrade->base.x - scroll_x, pupgrade->base.y, + NO_UPDATE); + } + else if (pupgrade->kind == UPGRADE_HERRING) + { + texture_draw(&img_golden_herring, + pupgrade->base.x - scroll_x, pupgrade->base.y, + NO_UPDATE); + } + } + } +} + +void upgrade_collision(upgrade_type* pupgrade, void* p_c_object, int c_object) +{ + player_type* pplayer = NULL; + + switch (c_object) + { + case CO_PLAYER: + /* Remove the upgrade: */ + + /* p_c_object is CO_PLAYER, so assign it to pplayer */ + pplayer = (player_type*) p_c_object; + + pupgrade->base.alive = NO; + + /* Affect the player: */ + + if (pupgrade->kind == UPGRADE_MINTS) + { + play_sound(sounds[SND_EXCELLENT], SOUND_CENTER_SPEAKER); + pplayer->size = BIG; + pplayer->base.height = 64; + pplayer->base.y -= 32; + if(collision_object_map(&pplayer->base)) + { + pplayer->base.height = 32; + pplayer->base.y += 32; + pplayer->duck = YES; + } + timer_start(&super_bkgd_timer, 350); + } + else if (pupgrade->kind == UPGRADE_COFFEE) + { + play_sound(sounds[SND_COFFEE], SOUND_CENTER_SPEAKER); + pplayer->got_coffee = YES; + timer_start(&super_bkgd_timer, 250); + } + else if (pupgrade->kind == UPGRADE_HERRING) + { + play_sound(sounds[SND_HERRING], SOUND_CENTER_SPEAKER); + timer_start(&pplayer->invincible_timer,TUX_INVINCIBLE_TIME); + timer_start(&super_bkgd_timer, 250); + /* play the herring song ^^ */ + if (get_current_music() != HURRYUP_MUSIC) + { + set_current_music(HERRING_MUSIC); + play_current_music(); + } + } + break; + } +} + diff --git a/src/supertux.c b/src/supertux.c deleted file mode 100644 index 44aebe5f3..000000000 --- a/src/supertux.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - supertux.c - - Super Tux - - by Bill Kendrick & Tobias Glaesser - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 11, 2000 - March 15, 2004 -*/ - - -#include "supertux.h" - - -/* --- MAIN --- */ - -#ifdef WIN32 -main(int argc, char * argv[]) -#else -int main(int argc, char * argv[]) -#endif -{ - int done; - - parseargs(argc, argv); - - st_directory_setup(); - st_audio_setup(); - st_video_setup(); - st_joystick_setup(); - st_general_setup(); - st_menu(); - - done = intro(); - - done = 0; - - while (!done) - { - done = title(); - } - - clearscreen(0, 0, 0); - updatescreen(); - - st_shutdown(); - - return(0); -} diff --git a/src/supertux.cpp b/src/supertux.cpp new file mode 100644 index 000000000..44aebe5f3 --- /dev/null +++ b/src/supertux.cpp @@ -0,0 +1,51 @@ +/* + supertux.c + + Super Tux + + by Bill Kendrick & Tobias Glaesser + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 11, 2000 - March 15, 2004 +*/ + + +#include "supertux.h" + + +/* --- MAIN --- */ + +#ifdef WIN32 +main(int argc, char * argv[]) +#else +int main(int argc, char * argv[]) +#endif +{ + int done; + + parseargs(argc, argv); + + st_directory_setup(); + st_audio_setup(); + st_video_setup(); + st_joystick_setup(); + st_general_setup(); + st_menu(); + + done = intro(); + + done = 0; + + while (!done) + { + done = title(); + } + + clearscreen(0, 0, 0); + updatescreen(); + + st_shutdown(); + + return(0); +} diff --git a/src/text.c b/src/text.c deleted file mode 100644 index 666425855..000000000 --- a/src/text.c +++ /dev/null @@ -1,173 +0,0 @@ -// -// C Implementation: text -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include -#include -#include "globals.h" -#include "defines.h" -#include "screen.h" -#include "text.h" - -void text_load(text_type* ptext, char* file, int kind, int w, int h) -{ - int x, y; - int mx, my; - SDL_Surface *conv; - int pixels; - int i; - - if(kind == TEXT_TEXT) - { - mx = 26; - my = 3; - } - else if(kind == TEXT_NUM) - { - mx = 10; - my = 1; - } - else - { - mx = 0; - my = 0; - } - ptext->kind = kind; - ptext->w = w; - ptext->h = h; - - texture_load(&ptext->chars, file, USE_ALPHA); - - /* Load shadow font. */ - conv = SDL_DisplayFormatAlpha(ptext->chars.sdl_surface); - pixels = conv->w * conv->h; - SDL_LockSurface(conv); - for(i = 0; i < pixels; ++i) - { - Uint32 *p = (Uint32 *)conv->pixels + i; - *p = *p & conv->format->Amask; - } - SDL_UnlockSurface(conv); - SDL_SetAlpha(conv, SDL_SRCALPHA, 128); - texture_from_sdl_surface(&ptext->shadow_chars,conv,USE_ALPHA); - - SDL_FreeSurface(conv); -} - -void text_draw(text_type* ptext, char* text, int x, int y, int shadowsize, int update) -{ - if(text != NULL) - { - if(shadowsize != 0) - text_draw_chars(ptext,&ptext->shadow_chars, text,x+shadowsize,y+shadowsize, update); - - text_draw_chars(ptext,&ptext->chars, text,x,y, update); - } -} - -void text_draw_chars(text_type* ptext, texture_type* pchars, char* text, int x, int y, int update) -{ - int i,j,len; - int w, h; - - len = strlen(text); - w = ptext->w; - h = ptext->h; - - if(ptext->kind == TEXT_TEXT) - { - for( i = 0, j = 0; i < len; ++i,++j) - { - if( text[i] >= 'A' && text[i] <= 'Z') - texture_draw_part(pchars, (int)(text[i] - 'A')*w, 0, x+(j*w), y, ptext->w, ptext->h, update); - else if( text[i] >= 'a' && text[i] <= 'z') - texture_draw_part(pchars, (int)(text[i] - 'a')*w, h, x+(j*w), y, ptext->w, ptext->h, update); - else if ( text[i] >= '!' && text[i] <= '9') - texture_draw_part(pchars, (int)(text[i] - '!')*w, h*2, x+(j*w), y, ptext->w, ptext->h, update); - else if ( text[i] == '?') - texture_draw_part(pchars, 25*w, h*2, x+(j*w), y, ptext->w, ptext->h, update); - else if ( text[i] == '\n') - { - y += ptext->h + 2; - j = 0; - } - } - } - else if(ptext->kind == TEXT_NUM) - { - for( i = 0, j = 0; i < len; ++i, ++j) - { - if ( text[i] >= '0' && text[i] <= '9') - texture_draw_part(pchars, (int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, update); - else if ( text[i] == '\n') - { - y += ptext->h + 2; - j = 0; - } - } - } -} - -void text_drawf(text_type* ptext, char* text, int x, int y, int halign, int valign, int shadowsize, int update) -{ - if(text != NULL) - { - if(halign == A_RIGHT) /* FIXME: this doesn't work correctly for strings with newlines.*/ - x += screen->w - (strlen(text)*ptext->w); - else if(halign == A_HMIDDLE) - x += screen->w/2 - ((strlen(text)*ptext->w)/2); - - if(valign == A_BOTTOM) - y += screen->h - ptext->h; - else if(valign == A_VMIDDLE) - y += screen->h/2 - ptext->h/2; - - text_draw(ptext,text,x,y,shadowsize,update); - } -} - -void text_free(text_type* ptext) -{ - int c; - if(ptext->kind == TEXT_TEXT) - texture_free(&ptext->chars); - else if(ptext->kind == TEXT_NUM) - texture_free(&ptext->chars); -} - -/* --- ERASE TEXT: --- */ - -void erasetext(text_type* ptext, char * text, int x, int y, texture_type * ptexture, int update, int shadowsize) -{ - SDL_Rect dest; - - - dest.x = x; - dest.y = y; - dest.w = strlen(text) * ptext->w + shadowsize; - dest.h = ptext->h; - - if (dest.w > screen->w) - dest.w = screen->w; - - texture_draw_part(ptexture,dest.x,dest.y,dest.x,dest.y,dest.w,dest.h,update); - - if (update == UPDATE) - update_rect(screen, dest.x, dest.y, dest.w, dest.h); -} - - -/* --- ERASE CENTERED TEXT: --- */ - -void erasecenteredtext(text_type* ptext, char * text, int y, texture_type * ptexture, int update, int shadowsize) -{ - erasetext(ptext, text, screen->w / 2 - (strlen(text) * 8), y, ptexture, update, shadowsize); -} diff --git a/src/text.cpp b/src/text.cpp new file mode 100644 index 000000000..666425855 --- /dev/null +++ b/src/text.cpp @@ -0,0 +1,173 @@ +// +// C Implementation: text +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include +#include "globals.h" +#include "defines.h" +#include "screen.h" +#include "text.h" + +void text_load(text_type* ptext, char* file, int kind, int w, int h) +{ + int x, y; + int mx, my; + SDL_Surface *conv; + int pixels; + int i; + + if(kind == TEXT_TEXT) + { + mx = 26; + my = 3; + } + else if(kind == TEXT_NUM) + { + mx = 10; + my = 1; + } + else + { + mx = 0; + my = 0; + } + ptext->kind = kind; + ptext->w = w; + ptext->h = h; + + texture_load(&ptext->chars, file, USE_ALPHA); + + /* Load shadow font. */ + conv = SDL_DisplayFormatAlpha(ptext->chars.sdl_surface); + pixels = conv->w * conv->h; + SDL_LockSurface(conv); + for(i = 0; i < pixels; ++i) + { + Uint32 *p = (Uint32 *)conv->pixels + i; + *p = *p & conv->format->Amask; + } + SDL_UnlockSurface(conv); + SDL_SetAlpha(conv, SDL_SRCALPHA, 128); + texture_from_sdl_surface(&ptext->shadow_chars,conv,USE_ALPHA); + + SDL_FreeSurface(conv); +} + +void text_draw(text_type* ptext, char* text, int x, int y, int shadowsize, int update) +{ + if(text != NULL) + { + if(shadowsize != 0) + text_draw_chars(ptext,&ptext->shadow_chars, text,x+shadowsize,y+shadowsize, update); + + text_draw_chars(ptext,&ptext->chars, text,x,y, update); + } +} + +void text_draw_chars(text_type* ptext, texture_type* pchars, char* text, int x, int y, int update) +{ + int i,j,len; + int w, h; + + len = strlen(text); + w = ptext->w; + h = ptext->h; + + if(ptext->kind == TEXT_TEXT) + { + for( i = 0, j = 0; i < len; ++i,++j) + { + if( text[i] >= 'A' && text[i] <= 'Z') + texture_draw_part(pchars, (int)(text[i] - 'A')*w, 0, x+(j*w), y, ptext->w, ptext->h, update); + else if( text[i] >= 'a' && text[i] <= 'z') + texture_draw_part(pchars, (int)(text[i] - 'a')*w, h, x+(j*w), y, ptext->w, ptext->h, update); + else if ( text[i] >= '!' && text[i] <= '9') + texture_draw_part(pchars, (int)(text[i] - '!')*w, h*2, x+(j*w), y, ptext->w, ptext->h, update); + else if ( text[i] == '?') + texture_draw_part(pchars, 25*w, h*2, x+(j*w), y, ptext->w, ptext->h, update); + else if ( text[i] == '\n') + { + y += ptext->h + 2; + j = 0; + } + } + } + else if(ptext->kind == TEXT_NUM) + { + for( i = 0, j = 0; i < len; ++i, ++j) + { + if ( text[i] >= '0' && text[i] <= '9') + texture_draw_part(pchars, (int)(text[i] - '0')*w, 0, x+(j*w), y, w, h, update); + else if ( text[i] == '\n') + { + y += ptext->h + 2; + j = 0; + } + } + } +} + +void text_drawf(text_type* ptext, char* text, int x, int y, int halign, int valign, int shadowsize, int update) +{ + if(text != NULL) + { + if(halign == A_RIGHT) /* FIXME: this doesn't work correctly for strings with newlines.*/ + x += screen->w - (strlen(text)*ptext->w); + else if(halign == A_HMIDDLE) + x += screen->w/2 - ((strlen(text)*ptext->w)/2); + + if(valign == A_BOTTOM) + y += screen->h - ptext->h; + else if(valign == A_VMIDDLE) + y += screen->h/2 - ptext->h/2; + + text_draw(ptext,text,x,y,shadowsize,update); + } +} + +void text_free(text_type* ptext) +{ + int c; + if(ptext->kind == TEXT_TEXT) + texture_free(&ptext->chars); + else if(ptext->kind == TEXT_NUM) + texture_free(&ptext->chars); +} + +/* --- ERASE TEXT: --- */ + +void erasetext(text_type* ptext, char * text, int x, int y, texture_type * ptexture, int update, int shadowsize) +{ + SDL_Rect dest; + + + dest.x = x; + dest.y = y; + dest.w = strlen(text) * ptext->w + shadowsize; + dest.h = ptext->h; + + if (dest.w > screen->w) + dest.w = screen->w; + + texture_draw_part(ptexture,dest.x,dest.y,dest.x,dest.y,dest.w,dest.h,update); + + if (update == UPDATE) + update_rect(screen, dest.x, dest.y, dest.w, dest.h); +} + + +/* --- ERASE CENTERED TEXT: --- */ + +void erasecenteredtext(text_type* ptext, char * text, int y, texture_type * ptexture, int update, int shadowsize) +{ + erasetext(ptext, text, screen->w / 2 - (strlen(text) * 8), y, ptexture, update, shadowsize); +} diff --git a/src/texture.c b/src/texture.c deleted file mode 100644 index 05c3d3423..000000000 --- a/src/texture.c +++ /dev/null @@ -1,401 +0,0 @@ -// -// C Implementation: texture -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "SDL.h" -#include "SDL_image.h" -#include "globals.h" -#include "screen.h" -#include "setup.h" -#include "texture.h" - -void (*texture_load) (texture_type* ptexture, char * file, int use_alpha); -void (*texture_load_part) (texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha); -void (*texture_free) (texture_type* ptexture); -void (*texture_draw) (texture_type* ptexture, float x, float y, int update); -void (*texture_draw_bg) (texture_type* ptexture, int update); -void (*texture_draw_part) (texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update); - - -void texture_setup(void) -{ -#ifdef NOOPENGL - texture_load = texture_load_sdl; - texture_load_part = texture_load_part_sdl; - texture_free = texture_free_sdl; - texture_draw = texture_draw_sdl; - texture_draw_bg = texture_draw_bg_sdl; - texture_draw_part = texture_draw_part_sdl; -#else - - if(use_gl) - { - texture_load = texture_load_gl; - texture_load_part = texture_load_part_gl; - texture_free = texture_free_gl; - texture_draw = texture_draw_gl; - texture_draw_bg = texture_draw_bg_gl; - texture_draw_part = texture_draw_part_gl; - } - else - { - texture_load = texture_load_sdl; - texture_load_part = texture_load_part_sdl; - texture_free = texture_free_sdl; - texture_draw = texture_draw_sdl; - texture_draw_bg = texture_draw_bg_sdl; - texture_draw_part = texture_draw_part_sdl; - } -#endif -} - -#ifndef NOOPENGL -void texture_load_gl(texture_type* ptexture, char * file, int use_alpha) -{ - texture_load_sdl(ptexture,file,use_alpha); - texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture); -} - -void texture_load_part_gl(texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha) -{ - texture_load_part_sdl(ptexture,file,x,y,w,h,use_alpha); - texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture); -} - -/* Quick utility function for texture creation */ -static int power_of_two(int input) -{ - int value = 1; - - while ( value < input ) { - value <<= 1; - } - return value; -} - -void texture_create_gl(SDL_Surface * surf, GLuint * tex) -{ - Uint32 saved_flags; - Uint8 saved_alpha; - int w, h; - SDL_Surface *conv; - - w = power_of_two(surf->w); - h = power_of_two(surf->h), - conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel, -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); -#else - - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); -#endif - - /* Save the alpha blending attributes */ - saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); - saved_alpha = surf->format->alpha; - if ( (saved_flags & SDL_SRCALPHA) - == SDL_SRCALPHA ) - { - SDL_SetAlpha(surf, 0, 0); - } - - SDL_BlitSurface(surf, 0, conv, 0); - - /* Restore the alpha blending attributes */ - if ( (saved_flags & SDL_SRCALPHA) - == SDL_SRCALPHA ) - { - SDL_SetAlpha(surf, saved_flags, saved_alpha); - } - - glGenTextures(1, &*tex); - glBindTexture(GL_TEXTURE_2D , *tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - SDL_FreeSurface(conv); -} - -void texture_free_gl(texture_type* ptexture) -{ - SDL_FreeSurface(ptexture->sdl_surface); - glDeleteTextures(1, &ptexture->gl_texture); -} - -void texture_draw_gl(texture_type* ptexture, float x, float y, int update) -{ -float pw = power_of_two(ptexture->w); -float ph = power_of_two(ptexture->h); - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glColor4ub(255, 255, 255,255); - - glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(x, y); - glTexCoord2f((float)ptexture->w / pw, 0); - glVertex2f((float)ptexture->w+x, y); - glTexCoord2f((float)ptexture->w / pw, (float)ptexture->h / ph); glVertex2f((float)ptexture->w+x, (float)ptexture->h+y); - glTexCoord2f(0, (float)ptexture->h / ph); - glVertex2f(x, (float)ptexture->h+y); - glEnd(); - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); -} - -void texture_draw_bg_gl(texture_type* ptexture, int update) -{ -float pw = power_of_two(ptexture->w); -float ph = power_of_two(ptexture->h); - - glColor3ub(255, 255, 255); - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(0, 0); - glTexCoord2f((float)ptexture->w / pw, 0); - glVertex2f(screen->w, 0); - glTexCoord2f((float)ptexture->w / pw, (float)ptexture->h / ph); - glVertex2f(screen->w, screen->h); - glTexCoord2f(0, (float)ptexture->h / ph); - glVertex2f(0, screen->h); - glEnd(); - - glDisable(GL_TEXTURE_2D); -} - -void texture_draw_part_gl(texture_type* ptexture,float sx, float sy, float x, float y, float w, float h, int update) -{ -float pw = power_of_two(ptexture->w); -float ph = power_of_two(ptexture->h); - - glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glColor4ub(255, 255, 255,255); - - glEnable(GL_TEXTURE_2D); - - - glBegin(GL_QUADS); - glTexCoord2f(sx / pw, sy / ph); - glVertex2f(x, y); - glTexCoord2f((float)(sx + w) / pw, sy / ph); - glVertex2f(w+x, y); - glTexCoord2f((sx+w) / pw, (sy+h) / ph); - glVertex2f(w +x, h+y); - glTexCoord2f(sx / pw, (float)(sy+h) / ph); - glVertex2f(x, h+y); - glEnd(); - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - -} -#endif - -void texture_load_sdl(texture_type* ptexture, char * file, int use_alpha) -{ - SDL_Surface * temp; - - temp = IMG_Load(file); - - if (temp == NULL) - st_abort("Can't load", file); - - if(use_alpha == IGNORE_ALPHA && !use_gl) - ptexture->sdl_surface = SDL_DisplayFormat(temp); - else - ptexture->sdl_surface = SDL_DisplayFormatAlpha(temp); - - if (ptexture->sdl_surface == NULL) - st_abort("Can't covert to display format", file); - - if (use_alpha == IGNORE_ALPHA && !use_gl) - SDL_SetAlpha(ptexture->sdl_surface, 0, 0); - - SDL_FreeSurface(temp); - - ptexture->w = ptexture->sdl_surface->w; - ptexture->h = ptexture->sdl_surface->h; - -} - -void texture_load_part_sdl(texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha) -{ - - SDL_Rect src; - SDL_Surface * temp; - SDL_Surface * conv; - - temp = IMG_Load(file); - - if (temp == NULL) - st_abort("Can't load", file); - - /* Set source rectangle for conv: */ - - src.x = x; - src.y = y; - src.w = w; - src.h = h; - - conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel, - temp->format->Rmask, - temp->format->Gmask, - temp->format->Bmask, - temp->format->Amask); - - /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN - 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); - #else - - 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); - #endif*/ - - SDL_SetAlpha(temp,0,0); - - SDL_BlitSurface(temp, &src, conv, NULL); - if(use_alpha == IGNORE_ALPHA && !use_gl) - ptexture->sdl_surface = SDL_DisplayFormat(conv); - else - ptexture->sdl_surface = SDL_DisplayFormatAlpha(conv); - - if (ptexture->sdl_surface == NULL) - st_abort("Can't covert to display format", file); - - if (use_alpha == IGNORE_ALPHA && !use_gl) - SDL_SetAlpha(ptexture->sdl_surface, 0, 0); - - SDL_FreeSurface(temp); - SDL_FreeSurface(conv); - - ptexture->w = ptexture->sdl_surface->w; - ptexture->h = ptexture->sdl_surface->h; -} - -void texture_from_sdl_surface(texture_type* ptexture, SDL_Surface* sdl_surf, int use_alpha) -{ - Uint32 saved_flags; - Uint8 saved_alpha; - - /* Save the alpha blending attributes */ - saved_flags = sdl_surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); - saved_alpha = sdl_surf->format->alpha; - if ( (saved_flags & SDL_SRCALPHA) - == SDL_SRCALPHA ) - { - SDL_SetAlpha(sdl_surf, 0, 0); - } - - if(use_alpha == IGNORE_ALPHA && !use_gl) - ptexture->sdl_surface = SDL_DisplayFormat(sdl_surf); - else - ptexture->sdl_surface = SDL_DisplayFormatAlpha(sdl_surf); - - /* Restore the alpha blending attributes */ - if ( (saved_flags & SDL_SRCALPHA) - == SDL_SRCALPHA ) - { - SDL_SetAlpha(ptexture->sdl_surface, saved_flags, saved_alpha); - } - - if (ptexture->sdl_surface == NULL) - st_abort("Can't covert to display format", "SURFACE"); - - if (use_alpha == IGNORE_ALPHA && !use_gl) - SDL_SetAlpha(ptexture->sdl_surface, 0, 0); - - ptexture->w = ptexture->sdl_surface->w; - ptexture->h = ptexture->sdl_surface->h; - -#ifndef NOOPENGL - - if(use_gl) - { - texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture); - } -#endif -} - -void texture_draw_sdl(texture_type* ptexture, float x, float y, int update) -{ - - SDL_Rect dest; - - dest.x = (int)x; - dest.y = (int)y; - dest.w = ptexture->w; - dest.h = ptexture->h; - SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); -} - - -void texture_draw_bg_sdl(texture_type* ptexture, int update) -{ - SDL_Rect dest; - - dest.x = 0; - dest.y = 0; - dest.w = screen->w; - dest.h = screen->h; - - SDL_SoftStretch(ptexture->sdl_surface, NULL, screen, &dest); - - if (update == UPDATE) - SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); -} - -void texture_draw_part_sdl(texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update) -{ - SDL_Rect src, dest; - - src.x = (int)sx; - src.y = (int)sy; - src.w = (int)w; - src.h = (int)h; - - dest.x = (int)x; - dest.y = (int)y; - dest.w = (int)w; - dest.h = (int)h; - - - SDL_BlitSurface(ptexture->sdl_surface, &src, screen, &dest); - - if (update == UPDATE) - update_rect(screen, dest.x, dest.y, dest.w, dest.h); -} - -void texture_free_sdl(texture_type* ptexture) -{ - SDL_FreeSurface(ptexture->sdl_surface); -} - diff --git a/src/texture.cpp b/src/texture.cpp new file mode 100644 index 000000000..05c3d3423 --- /dev/null +++ b/src/texture.cpp @@ -0,0 +1,401 @@ +// +// C Implementation: texture +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "SDL.h" +#include "SDL_image.h" +#include "globals.h" +#include "screen.h" +#include "setup.h" +#include "texture.h" + +void (*texture_load) (texture_type* ptexture, char * file, int use_alpha); +void (*texture_load_part) (texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha); +void (*texture_free) (texture_type* ptexture); +void (*texture_draw) (texture_type* ptexture, float x, float y, int update); +void (*texture_draw_bg) (texture_type* ptexture, int update); +void (*texture_draw_part) (texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update); + + +void texture_setup(void) +{ +#ifdef NOOPENGL + texture_load = texture_load_sdl; + texture_load_part = texture_load_part_sdl; + texture_free = texture_free_sdl; + texture_draw = texture_draw_sdl; + texture_draw_bg = texture_draw_bg_sdl; + texture_draw_part = texture_draw_part_sdl; +#else + + if(use_gl) + { + texture_load = texture_load_gl; + texture_load_part = texture_load_part_gl; + texture_free = texture_free_gl; + texture_draw = texture_draw_gl; + texture_draw_bg = texture_draw_bg_gl; + texture_draw_part = texture_draw_part_gl; + } + else + { + texture_load = texture_load_sdl; + texture_load_part = texture_load_part_sdl; + texture_free = texture_free_sdl; + texture_draw = texture_draw_sdl; + texture_draw_bg = texture_draw_bg_sdl; + texture_draw_part = texture_draw_part_sdl; + } +#endif +} + +#ifndef NOOPENGL +void texture_load_gl(texture_type* ptexture, char * file, int use_alpha) +{ + texture_load_sdl(ptexture,file,use_alpha); + texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture); +} + +void texture_load_part_gl(texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha) +{ + texture_load_part_sdl(ptexture,file,x,y,w,h,use_alpha); + texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture); +} + +/* Quick utility function for texture creation */ +static int power_of_two(int input) +{ + int value = 1; + + while ( value < input ) { + value <<= 1; + } + return value; +} + +void texture_create_gl(SDL_Surface * surf, GLuint * tex) +{ + Uint32 saved_flags; + Uint8 saved_alpha; + int w, h; + SDL_Surface *conv; + + w = power_of_two(surf->w); + h = power_of_two(surf->h), + conv = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, surf->format->BitsPerPixel, +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); +#else + + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); +#endif + + /* Save the alpha blending attributes */ + saved_flags = surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + saved_alpha = surf->format->alpha; + if ( (saved_flags & SDL_SRCALPHA) + == SDL_SRCALPHA ) + { + SDL_SetAlpha(surf, 0, 0); + } + + SDL_BlitSurface(surf, 0, conv, 0); + + /* Restore the alpha blending attributes */ + if ( (saved_flags & SDL_SRCALPHA) + == SDL_SRCALPHA ) + { + SDL_SetAlpha(surf, saved_flags, saved_alpha); + } + + glGenTextures(1, &*tex); + glBindTexture(GL_TEXTURE_2D , *tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, conv->pitch / conv->format->BytesPerPixel); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, conv->pixels); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + SDL_FreeSurface(conv); +} + +void texture_free_gl(texture_type* ptexture) +{ + SDL_FreeSurface(ptexture->sdl_surface); + glDeleteTextures(1, &ptexture->gl_texture); +} + +void texture_draw_gl(texture_type* ptexture, float x, float y, int update) +{ +float pw = power_of_two(ptexture->w); +float ph = power_of_two(ptexture->h); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glColor4ub(255, 255, 255,255); + + glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(x, y); + glTexCoord2f((float)ptexture->w / pw, 0); + glVertex2f((float)ptexture->w+x, y); + glTexCoord2f((float)ptexture->w / pw, (float)ptexture->h / ph); glVertex2f((float)ptexture->w+x, (float)ptexture->h+y); + glTexCoord2f(0, (float)ptexture->h / ph); + glVertex2f(x, (float)ptexture->h+y); + glEnd(); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); +} + +void texture_draw_bg_gl(texture_type* ptexture, int update) +{ +float pw = power_of_two(ptexture->w); +float ph = power_of_two(ptexture->h); + + glColor3ub(255, 255, 255); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(0, 0); + glTexCoord2f((float)ptexture->w / pw, 0); + glVertex2f(screen->w, 0); + glTexCoord2f((float)ptexture->w / pw, (float)ptexture->h / ph); + glVertex2f(screen->w, screen->h); + glTexCoord2f(0, (float)ptexture->h / ph); + glVertex2f(0, screen->h); + glEnd(); + + glDisable(GL_TEXTURE_2D); +} + +void texture_draw_part_gl(texture_type* ptexture,float sx, float sy, float x, float y, float w, float h, int update) +{ +float pw = power_of_two(ptexture->w); +float ph = power_of_two(ptexture->h); + + glBindTexture(GL_TEXTURE_2D, ptexture->gl_texture); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glColor4ub(255, 255, 255,255); + + glEnable(GL_TEXTURE_2D); + + + glBegin(GL_QUADS); + glTexCoord2f(sx / pw, sy / ph); + glVertex2f(x, y); + glTexCoord2f((float)(sx + w) / pw, sy / ph); + glVertex2f(w+x, y); + glTexCoord2f((sx+w) / pw, (sy+h) / ph); + glVertex2f(w +x, h+y); + glTexCoord2f(sx / pw, (float)(sy+h) / ph); + glVertex2f(x, h+y); + glEnd(); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + +} +#endif + +void texture_load_sdl(texture_type* ptexture, char * file, int use_alpha) +{ + SDL_Surface * temp; + + temp = IMG_Load(file); + + if (temp == NULL) + st_abort("Can't load", file); + + if(use_alpha == IGNORE_ALPHA && !use_gl) + ptexture->sdl_surface = SDL_DisplayFormat(temp); + else + ptexture->sdl_surface = SDL_DisplayFormatAlpha(temp); + + if (ptexture->sdl_surface == NULL) + st_abort("Can't covert to display format", file); + + if (use_alpha == IGNORE_ALPHA && !use_gl) + SDL_SetAlpha(ptexture->sdl_surface, 0, 0); + + SDL_FreeSurface(temp); + + ptexture->w = ptexture->sdl_surface->w; + ptexture->h = ptexture->sdl_surface->h; + +} + +void texture_load_part_sdl(texture_type* ptexture, char * file, int x, int y, int w, int h, int use_alpha) +{ + + SDL_Rect src; + SDL_Surface * temp; + SDL_Surface * conv; + + temp = IMG_Load(file); + + if (temp == NULL) + st_abort("Can't load", file); + + /* Set source rectangle for conv: */ + + src.x = x; + src.y = y; + src.w = w; + src.h = h; + + conv = SDL_CreateRGBSurface(temp->flags, w, h, temp->format->BitsPerPixel, + temp->format->Rmask, + temp->format->Gmask, + temp->format->Bmask, + temp->format->Amask); + + /* #if SDL_BYTEORDER == SDL_BIG_ENDIAN + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); + #else + + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); + #endif*/ + + SDL_SetAlpha(temp,0,0); + + SDL_BlitSurface(temp, &src, conv, NULL); + if(use_alpha == IGNORE_ALPHA && !use_gl) + ptexture->sdl_surface = SDL_DisplayFormat(conv); + else + ptexture->sdl_surface = SDL_DisplayFormatAlpha(conv); + + if (ptexture->sdl_surface == NULL) + st_abort("Can't covert to display format", file); + + if (use_alpha == IGNORE_ALPHA && !use_gl) + SDL_SetAlpha(ptexture->sdl_surface, 0, 0); + + SDL_FreeSurface(temp); + SDL_FreeSurface(conv); + + ptexture->w = ptexture->sdl_surface->w; + ptexture->h = ptexture->sdl_surface->h; +} + +void texture_from_sdl_surface(texture_type* ptexture, SDL_Surface* sdl_surf, int use_alpha) +{ + Uint32 saved_flags; + Uint8 saved_alpha; + + /* Save the alpha blending attributes */ + saved_flags = sdl_surf->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + saved_alpha = sdl_surf->format->alpha; + if ( (saved_flags & SDL_SRCALPHA) + == SDL_SRCALPHA ) + { + SDL_SetAlpha(sdl_surf, 0, 0); + } + + if(use_alpha == IGNORE_ALPHA && !use_gl) + ptexture->sdl_surface = SDL_DisplayFormat(sdl_surf); + else + ptexture->sdl_surface = SDL_DisplayFormatAlpha(sdl_surf); + + /* Restore the alpha blending attributes */ + if ( (saved_flags & SDL_SRCALPHA) + == SDL_SRCALPHA ) + { + SDL_SetAlpha(ptexture->sdl_surface, saved_flags, saved_alpha); + } + + if (ptexture->sdl_surface == NULL) + st_abort("Can't covert to display format", "SURFACE"); + + if (use_alpha == IGNORE_ALPHA && !use_gl) + SDL_SetAlpha(ptexture->sdl_surface, 0, 0); + + ptexture->w = ptexture->sdl_surface->w; + ptexture->h = ptexture->sdl_surface->h; + +#ifndef NOOPENGL + + if(use_gl) + { + texture_create_gl(ptexture->sdl_surface,&ptexture->gl_texture); + } +#endif +} + +void texture_draw_sdl(texture_type* ptexture, float x, float y, int update) +{ + + SDL_Rect dest; + + dest.x = (int)x; + dest.y = (int)y; + dest.w = ptexture->w; + dest.h = ptexture->h; + SDL_BlitSurface(ptexture->sdl_surface, NULL, screen, &dest); + + if (update == UPDATE) + SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); +} + + +void texture_draw_bg_sdl(texture_type* ptexture, int update) +{ + SDL_Rect dest; + + dest.x = 0; + dest.y = 0; + dest.w = screen->w; + dest.h = screen->h; + + SDL_SoftStretch(ptexture->sdl_surface, NULL, screen, &dest); + + if (update == UPDATE) + SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h); +} + +void texture_draw_part_sdl(texture_type* ptexture, float sx, float sy, float x, float y, float w, float h, int update) +{ + SDL_Rect src, dest; + + src.x = (int)sx; + src.y = (int)sy; + src.w = (int)w; + src.h = (int)h; + + dest.x = (int)x; + dest.y = (int)y; + dest.w = (int)w; + dest.h = (int)h; + + + SDL_BlitSurface(ptexture->sdl_surface, &src, screen, &dest); + + if (update == UPDATE) + update_rect(screen, dest.x, dest.y, dest.w, dest.h); +} + +void texture_free_sdl(texture_type* ptexture) +{ + SDL_FreeSurface(ptexture->sdl_surface); +} + diff --git a/src/timer.c b/src/timer.c deleted file mode 100644 index 25a63a37a..000000000 --- a/src/timer.c +++ /dev/null @@ -1,134 +0,0 @@ -// -// C Implementation: timer -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "SDL.h" -#include "defines.h" -#include "timer.h" - -unsigned int st_pause_ticks, st_pause_count; - -unsigned int st_get_ticks(void) -{ - if(st_pause_count != 0) - return SDL_GetTicks() - st_pause_ticks - SDL_GetTicks() + st_pause_count; - else - return SDL_GetTicks() - st_pause_ticks; -} - -void st_pause_ticks_init(void) -{ - st_pause_ticks = 0; - st_pause_count = 0; -} - -void st_pause_ticks_start(void) -{ - st_pause_count = SDL_GetTicks(); -} - -void st_pause_ticks_stop(void) -{ - st_pause_ticks += SDL_GetTicks() - st_pause_count; - st_pause_count = 0; -} - -void timer_init(timer_type* ptimer, int st_ticks) -{ - ptimer->period = 0; - ptimer->time = 0; - - if(st_ticks == YES) - ptimer->get_ticks = st_get_ticks; - else - ptimer->get_ticks = SDL_GetTicks; - -} - -void timer_start(timer_type* ptimer, unsigned int period) -{ - ptimer->time = ptimer->get_ticks(); - ptimer->period = period; -} - -void timer_stop(timer_type* ptimer) -{ - if(ptimer->get_ticks == st_get_ticks) - timer_init(ptimer,YES); - else - timer_init(ptimer,NO); -} - -int timer_check(timer_type* ptimer) -{ - if((ptimer->time != 0) && (ptimer->time + ptimer->period > ptimer->get_ticks())) - return YES; - else - { - ptimer->time = 0; - return NO; - } -} - -int timer_started(timer_type* ptimer) -{ - if(ptimer->time != 0) - return YES; - else - return NO; -} - -int timer_get_left(timer_type* ptimer) -{ - return (ptimer->period - (ptimer->get_ticks() - ptimer->time)); -} - -int timer_get_gone(timer_type* ptimer) -{ - return (ptimer->get_ticks() - ptimer->time); -} - -int timer_fwrite(timer_type* ptimer, FILE* fi) -{ - unsigned int diff_ticks; - int tick_mode; - if(ptimer->time != 0) - diff_ticks = ptimer->get_ticks() - ptimer->time; - else - diff_ticks = 0; - - fwrite(&ptimer->period,sizeof(unsigned int),1,fi); - fwrite(&diff_ticks,sizeof(unsigned int),1,fi); - if(ptimer->get_ticks == st_get_ticks) - tick_mode = YES; - else - tick_mode = NO; - fwrite(&tick_mode,sizeof(unsigned int),1,fi); -} - -int timer_fread(timer_type* ptimer, FILE* fi) -{ - unsigned int diff_ticks; - int tick_mode; - fread(&ptimer->period,sizeof(unsigned int),1,fi); - fread(&diff_ticks,sizeof(unsigned int),1,fi); - fread(&tick_mode,sizeof(unsigned int),1,fi); - if(tick_mode == YES) - ptimer->get_ticks = st_get_ticks; - else - ptimer->get_ticks = SDL_GetTicks; - if(diff_ticks != 0) - ptimer->time = ptimer->get_ticks() - diff_ticks; - else - ptimer->time = 0; - -} - diff --git a/src/timer.cpp b/src/timer.cpp new file mode 100644 index 000000000..25a63a37a --- /dev/null +++ b/src/timer.cpp @@ -0,0 +1,134 @@ +// +// C Implementation: timer +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "SDL.h" +#include "defines.h" +#include "timer.h" + +unsigned int st_pause_ticks, st_pause_count; + +unsigned int st_get_ticks(void) +{ + if(st_pause_count != 0) + return SDL_GetTicks() - st_pause_ticks - SDL_GetTicks() + st_pause_count; + else + return SDL_GetTicks() - st_pause_ticks; +} + +void st_pause_ticks_init(void) +{ + st_pause_ticks = 0; + st_pause_count = 0; +} + +void st_pause_ticks_start(void) +{ + st_pause_count = SDL_GetTicks(); +} + +void st_pause_ticks_stop(void) +{ + st_pause_ticks += SDL_GetTicks() - st_pause_count; + st_pause_count = 0; +} + +void timer_init(timer_type* ptimer, int st_ticks) +{ + ptimer->period = 0; + ptimer->time = 0; + + if(st_ticks == YES) + ptimer->get_ticks = st_get_ticks; + else + ptimer->get_ticks = SDL_GetTicks; + +} + +void timer_start(timer_type* ptimer, unsigned int period) +{ + ptimer->time = ptimer->get_ticks(); + ptimer->period = period; +} + +void timer_stop(timer_type* ptimer) +{ + if(ptimer->get_ticks == st_get_ticks) + timer_init(ptimer,YES); + else + timer_init(ptimer,NO); +} + +int timer_check(timer_type* ptimer) +{ + if((ptimer->time != 0) && (ptimer->time + ptimer->period > ptimer->get_ticks())) + return YES; + else + { + ptimer->time = 0; + return NO; + } +} + +int timer_started(timer_type* ptimer) +{ + if(ptimer->time != 0) + return YES; + else + return NO; +} + +int timer_get_left(timer_type* ptimer) +{ + return (ptimer->period - (ptimer->get_ticks() - ptimer->time)); +} + +int timer_get_gone(timer_type* ptimer) +{ + return (ptimer->get_ticks() - ptimer->time); +} + +int timer_fwrite(timer_type* ptimer, FILE* fi) +{ + unsigned int diff_ticks; + int tick_mode; + if(ptimer->time != 0) + diff_ticks = ptimer->get_ticks() - ptimer->time; + else + diff_ticks = 0; + + fwrite(&ptimer->period,sizeof(unsigned int),1,fi); + fwrite(&diff_ticks,sizeof(unsigned int),1,fi); + if(ptimer->get_ticks == st_get_ticks) + tick_mode = YES; + else + tick_mode = NO; + fwrite(&tick_mode,sizeof(unsigned int),1,fi); +} + +int timer_fread(timer_type* ptimer, FILE* fi) +{ + unsigned int diff_ticks; + int tick_mode; + fread(&ptimer->period,sizeof(unsigned int),1,fi); + fread(&diff_ticks,sizeof(unsigned int),1,fi); + fread(&tick_mode,sizeof(unsigned int),1,fi); + if(tick_mode == YES) + ptimer->get_ticks = st_get_ticks; + else + ptimer->get_ticks = SDL_GetTicks; + if(diff_ticks != 0) + ptimer->time = ptimer->get_ticks() - diff_ticks; + else + ptimer->time = 0; + +} + diff --git a/src/title.c b/src/title.c deleted file mode 100644 index ea74ca864..000000000 --- a/src/title.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - title.c - - Super Tux - Title Screen - - by Bill Kendrick - bill@newbreedsoftware.com - http://www.newbreedsoftware.com/supertux/ - - April 11, 2000 - March 15, 2004 -*/ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef LINUX -#include -#include -#include -#endif - -#include "defines.h" -#include "globals.h" -#include "title.h" -#include "screen.h" -#include "high_scores.h" -#include "menu.h" -#include "texture.h" -#include "timer.h" -#include "setup.h" -#include "level.h" -#include "gameloop.h" -#include "leveleditor.h" - -static texture_type bkg_title, img_choose_subset, anim1, anim2; -static SDL_Event event; -static SDLKey key; -static int quit, frame, pict, i; - -void display_credits(); - -void draw_background() -{ - /* Draw the title background: */ - - texture_draw_bg(&bkg_title, NO_UPDATE); - - /* Animate title screen: */ - - pict = (frame / 5) % 3; - - if (pict == 0) - texture_draw_part(&bkg_title, 560, 270, 560, 270, 80, 75, NO_UPDATE); - else if (pict == 1) - texture_draw(&anim1, 560, 270, NO_UPDATE); - else if (pict == 2) - texture_draw(&anim2, 560, 270, NO_UPDATE); -} - -/* --- TITLE SCREEN --- */ - -int title(void) -{ - int done; - char str[80]; - string_list_type level_subsets; - st_subset subset; - level_subsets = dsubdirs("/levels", "info"); - - subset_init(&subset); - - /* Reset menu variables */ - menu_reset(); - menu_set_current(&main_menu); - - clearscreen(0, 0, 0); - updatescreen(); - - /* Load images: */ - - texture_load(&bkg_title,DATA_PREFIX "/images/title/title.png", IGNORE_ALPHA); - texture_load(&anim1,DATA_PREFIX "/images/title/title-anim2.png", IGNORE_ALPHA); - texture_load(&anim2,DATA_PREFIX "/images/title/title-anim1.png", IGNORE_ALPHA); - texture_load(&img_choose_subset,DATA_PREFIX "/images/status/choose-level-subset.png", USE_ALPHA); - - /* --- Main title loop: --- */ - - done = 0; - quit = 0; - show_menu = 1; - frame = 0; - - /* Draw the title background: */ - texture_draw_bg(&bkg_title, NO_UPDATE); - - load_hs(); - - while (!done && !quit) - { - /* Handle events: */ - - while (SDL_PollEvent(&event)) - { - if (event.type == SDL_QUIT) - { - /* Quit event - quit: */ - quit = 1; - } - else if (event.type == SDL_KEYDOWN) - { - /* Keypress... */ - - key = event.key.keysym.sym; - - /* Check for menu events */ - menu_event(&event.key.keysym); - - if (key == SDLK_ESCAPE) - { - /* Escape: Quit: */ - - quit = 1; - } - } -#ifdef JOY_YES - else if (event.type == SDL_JOYAXISMOTION && event.jaxis.axis == JOY_Y) - { - if (event.jaxis.value > 1024) - menuaction = MN_DOWN; - else if (event.jaxis.value < -1024) - menuaction = MN_UP; - } - else if (event.type == SDL_JOYBUTTONDOWN) - { - /* Joystick button: Continue: */ - - menuaction = MN_HIT; - } -#endif - - } - - /* Draw the background: */ - draw_background(); - - /* Draw the high score: */ - sprintf(str, "High score: %d", hs_score); - text_drawf(&gold_text, str, 0, -40, A_HMIDDLE, A_BOTTOM, 1, NO_UPDATE); - sprintf(str, "by %s", hs_name); - text_drawf(&gold_text, str, 0, -20, A_HMIDDLE, A_BOTTOM, 1, NO_UPDATE); - - /* Don't draw menu, if quit is true */ - if(show_menu && !quit) - menu_process_current(); - - if(current_menu == &main_menu) - { - switch (menu_check(&main_menu)) - { - case 2: - done = 0; - i = 0; - if(level_subsets.num_items != 0) - { - subset_load(&subset,level_subsets.item[0]); - while(!done) - { - texture_draw(&img_choose_subset,(screen->w - img_choose_subset.w) / 2, 0, NO_UPDATE); - if(level_subsets.num_items != 0) - { - texture_draw(&subset.image,(screen->w - subset.image.w) / 2 + 25,78,NO_UPDATE); - if(level_subsets.num_items > 1) - { - if(i > 0) - texture_draw(&arrow_left,(screen->w / 2) - ((strlen(subset.title)+2)*16)/2,20,NO_UPDATE); - if(i < level_subsets.num_items-1) - texture_draw(&arrow_right,(screen->w / 2) + ((strlen(subset.title))*16)/2,20,NO_UPDATE); - } - text_drawf(&gold_text, subset.title, 0, 20, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - text_drawf(&gold_text, subset.description, 20, -20, A_HMIDDLE, A_BOTTOM, 1, NO_UPDATE); - } - updatescreen(); - SDL_Delay(50); - while(SDL_PollEvent(&event) && !done) - { - switch(event.type) - { - case SDL_QUIT: - done = 1; - quit = 1; - break; - case SDL_KEYDOWN: // key pressed - /* Keypress... */ - - key = event.key.keysym.sym; - - if(key == SDLK_LEFT) - { - if(i > 0) - { - --i; - subset_free(&subset); - subset_load(&subset,level_subsets.item[i]); - } - } - else if(key == SDLK_RIGHT) - { - if(i < level_subsets.num_items -1) - { - ++i; - subset_free(&subset); - subset_load(&subset,level_subsets.item[i]); - } - } - else if(key == SDLK_SPACE || key == SDLK_RETURN) - { - done = YES; - quit = gameloop(subset.name,1,ST_GL_PLAY); - subset_free(&subset); - } - else if(key == SDLK_ESCAPE) - { - done = YES; - } - break; - default: - break; - } - } - } - } - break; - case 3: - update_load_save_game_menu(&load_game_menu, YES); - break; - case 5: - done = 1; - quit = leveleditor(1); - break; - case 6: - display_credits(); - break; - case 8: - quit = 1; - break; - } - } - else if(current_menu == &options_menu) - { - process_options_menu(); - } - else if(current_menu == &load_game_menu) - { - process_save_load_game_menu(NO); - } - - flipscreen(); - - /* Pause: */ - frame++; - SDL_Delay(50); - - } - /* Free surfaces: */ - - texture_free(&bkg_title); - texture_free(&anim1); - texture_free(&anim2); - string_list_free(&level_subsets); - - /* Return to main! */ - - return(quit); -} - -#define MAX_VEL 10 -#define SPEED 1 -#define SCROLL 60 - -void display_credits() -{ - int done; - int scroll, speed; - timer_type timer; - int n,d; - int length; - FILE* fi; - char temp[1024]; - string_list_type names; - char filename[1024]; - string_list_init(&names); - sprintf(filename,"%s/CREDITS",DATA_PREFIX); - if((fi = fopen(filename,"r")) != NULL) - { - while(fgets(temp, sizeof(temp), fi) != NULL) - { - temp[strlen(temp)-1]='\0'; - string_list_add_item(&names,temp); - } - fclose(fi); - } - else - { - string_list_add_item(&names,"Credits were not found!"); - string_list_add_item(&names,"Shame on the guy, who"); - string_list_add_item(&names,"forgot to include them"); - string_list_add_item(&names,"in your SuperTux distribution."); - } - - - timer_init(&timer, SDL_GetTicks()); - timer_start(&timer, 50); - - scroll = 0; - speed = 2; - done = 0; - - n = d = 0; - - length = names.num_items; - - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - - while(done == 0) - { - /* in case of input, exit */ - while(SDL_PollEvent(&event)) - switch(event.type) - { - case SDL_KEYDOWN: - switch(event.key.keysym.sym) - { - case SDLK_UP: - speed -= SPEED; - break; - case SDLK_DOWN: - speed += SPEED; - break; - case SDLK_SPACE: - case SDLK_RETURN: - if(speed >= 0) - scroll += SCROLL; - break; - case SDLK_ESCAPE: - done = 1; - break; - default: - break; - } - break; - case SDL_QUIT: - done = 1; - break; - default: - break; - } - - if(speed > MAX_VEL) - speed = MAX_VEL; - else if(speed < -MAX_VEL) - speed = -MAX_VEL; - - /* draw the credits */ - - draw_background(); - - text_drawf(&white_big_text, "- Credits -", 0, screen->h-scroll, A_HMIDDLE, A_TOP, 2, NO_UPDATE); - - for(i = 0, n = 0, d = 0; i < length; i++,n++,d++) - { - if(names.item[i] == "") - n--; - else - { - if(names.item[i][0] == ' ') - text_drawf(&white_small_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll-10, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - else if(names.item[i][0] == ' ') - text_drawf(&white_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - else if(names.item[i+1][0] == '-' || names.item[i][0] == '-') - text_drawf(&white_big_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 3, NO_UPDATE); - else - text_drawf(&blue_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 1, NO_UPDATE); - } - } - - - texture_draw_part(&bkg_title, 0, 0, 0, 0, 640, 130, NO_UPDATE); - - flipscreen(); - - if(60+screen->h+(n*18)+(d*18)-scroll < 0 && 20+60+screen->h+(n*18)+(d*18)-scroll < 0) - done = 1; - - scroll += speed; - if(scroll < 0) - scroll = 0; - - SDL_Delay(35); - - if(timer_get_left(&timer) < 0) - { - frame++; - timer_start(&timer, 50); - } - } - string_list_free(&names); - - SDL_EnableKeyRepeat(0, 0); // disables key repeating - show_menu = 1; - menu_set_current(&main_menu); -} diff --git a/src/title.cpp b/src/title.cpp new file mode 100644 index 000000000..ea74ca864 --- /dev/null +++ b/src/title.cpp @@ -0,0 +1,416 @@ +/* + title.c + + Super Tux - Title Screen + + by Bill Kendrick + bill@newbreedsoftware.com + http://www.newbreedsoftware.com/supertux/ + + April 11, 2000 - March 15, 2004 +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef LINUX +#include +#include +#include +#endif + +#include "defines.h" +#include "globals.h" +#include "title.h" +#include "screen.h" +#include "high_scores.h" +#include "menu.h" +#include "texture.h" +#include "timer.h" +#include "setup.h" +#include "level.h" +#include "gameloop.h" +#include "leveleditor.h" + +static texture_type bkg_title, img_choose_subset, anim1, anim2; +static SDL_Event event; +static SDLKey key; +static int quit, frame, pict, i; + +void display_credits(); + +void draw_background() +{ + /* Draw the title background: */ + + texture_draw_bg(&bkg_title, NO_UPDATE); + + /* Animate title screen: */ + + pict = (frame / 5) % 3; + + if (pict == 0) + texture_draw_part(&bkg_title, 560, 270, 560, 270, 80, 75, NO_UPDATE); + else if (pict == 1) + texture_draw(&anim1, 560, 270, NO_UPDATE); + else if (pict == 2) + texture_draw(&anim2, 560, 270, NO_UPDATE); +} + +/* --- TITLE SCREEN --- */ + +int title(void) +{ + int done; + char str[80]; + string_list_type level_subsets; + st_subset subset; + level_subsets = dsubdirs("/levels", "info"); + + subset_init(&subset); + + /* Reset menu variables */ + menu_reset(); + menu_set_current(&main_menu); + + clearscreen(0, 0, 0); + updatescreen(); + + /* Load images: */ + + texture_load(&bkg_title,DATA_PREFIX "/images/title/title.png", IGNORE_ALPHA); + texture_load(&anim1,DATA_PREFIX "/images/title/title-anim2.png", IGNORE_ALPHA); + texture_load(&anim2,DATA_PREFIX "/images/title/title-anim1.png", IGNORE_ALPHA); + texture_load(&img_choose_subset,DATA_PREFIX "/images/status/choose-level-subset.png", USE_ALPHA); + + /* --- Main title loop: --- */ + + done = 0; + quit = 0; + show_menu = 1; + frame = 0; + + /* Draw the title background: */ + texture_draw_bg(&bkg_title, NO_UPDATE); + + load_hs(); + + while (!done && !quit) + { + /* Handle events: */ + + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + /* Quit event - quit: */ + quit = 1; + } + else if (event.type == SDL_KEYDOWN) + { + /* Keypress... */ + + key = event.key.keysym.sym; + + /* Check for menu events */ + menu_event(&event.key.keysym); + + if (key == SDLK_ESCAPE) + { + /* Escape: Quit: */ + + quit = 1; + } + } +#ifdef JOY_YES + else if (event.type == SDL_JOYAXISMOTION && event.jaxis.axis == JOY_Y) + { + if (event.jaxis.value > 1024) + menuaction = MN_DOWN; + else if (event.jaxis.value < -1024) + menuaction = MN_UP; + } + else if (event.type == SDL_JOYBUTTONDOWN) + { + /* Joystick button: Continue: */ + + menuaction = MN_HIT; + } +#endif + + } + + /* Draw the background: */ + draw_background(); + + /* Draw the high score: */ + sprintf(str, "High score: %d", hs_score); + text_drawf(&gold_text, str, 0, -40, A_HMIDDLE, A_BOTTOM, 1, NO_UPDATE); + sprintf(str, "by %s", hs_name); + text_drawf(&gold_text, str, 0, -20, A_HMIDDLE, A_BOTTOM, 1, NO_UPDATE); + + /* Don't draw menu, if quit is true */ + if(show_menu && !quit) + menu_process_current(); + + if(current_menu == &main_menu) + { + switch (menu_check(&main_menu)) + { + case 2: + done = 0; + i = 0; + if(level_subsets.num_items != 0) + { + subset_load(&subset,level_subsets.item[0]); + while(!done) + { + texture_draw(&img_choose_subset,(screen->w - img_choose_subset.w) / 2, 0, NO_UPDATE); + if(level_subsets.num_items != 0) + { + texture_draw(&subset.image,(screen->w - subset.image.w) / 2 + 25,78,NO_UPDATE); + if(level_subsets.num_items > 1) + { + if(i > 0) + texture_draw(&arrow_left,(screen->w / 2) - ((strlen(subset.title)+2)*16)/2,20,NO_UPDATE); + if(i < level_subsets.num_items-1) + texture_draw(&arrow_right,(screen->w / 2) + ((strlen(subset.title))*16)/2,20,NO_UPDATE); + } + text_drawf(&gold_text, subset.title, 0, 20, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + text_drawf(&gold_text, subset.description, 20, -20, A_HMIDDLE, A_BOTTOM, 1, NO_UPDATE); + } + updatescreen(); + SDL_Delay(50); + while(SDL_PollEvent(&event) && !done) + { + switch(event.type) + { + case SDL_QUIT: + done = 1; + quit = 1; + break; + case SDL_KEYDOWN: // key pressed + /* Keypress... */ + + key = event.key.keysym.sym; + + if(key == SDLK_LEFT) + { + if(i > 0) + { + --i; + subset_free(&subset); + subset_load(&subset,level_subsets.item[i]); + } + } + else if(key == SDLK_RIGHT) + { + if(i < level_subsets.num_items -1) + { + ++i; + subset_free(&subset); + subset_load(&subset,level_subsets.item[i]); + } + } + else if(key == SDLK_SPACE || key == SDLK_RETURN) + { + done = YES; + quit = gameloop(subset.name,1,ST_GL_PLAY); + subset_free(&subset); + } + else if(key == SDLK_ESCAPE) + { + done = YES; + } + break; + default: + break; + } + } + } + } + break; + case 3: + update_load_save_game_menu(&load_game_menu, YES); + break; + case 5: + done = 1; + quit = leveleditor(1); + break; + case 6: + display_credits(); + break; + case 8: + quit = 1; + break; + } + } + else if(current_menu == &options_menu) + { + process_options_menu(); + } + else if(current_menu == &load_game_menu) + { + process_save_load_game_menu(NO); + } + + flipscreen(); + + /* Pause: */ + frame++; + SDL_Delay(50); + + } + /* Free surfaces: */ + + texture_free(&bkg_title); + texture_free(&anim1); + texture_free(&anim2); + string_list_free(&level_subsets); + + /* Return to main! */ + + return(quit); +} + +#define MAX_VEL 10 +#define SPEED 1 +#define SCROLL 60 + +void display_credits() +{ + int done; + int scroll, speed; + timer_type timer; + int n,d; + int length; + FILE* fi; + char temp[1024]; + string_list_type names; + char filename[1024]; + string_list_init(&names); + sprintf(filename,"%s/CREDITS",DATA_PREFIX); + if((fi = fopen(filename,"r")) != NULL) + { + while(fgets(temp, sizeof(temp), fi) != NULL) + { + temp[strlen(temp)-1]='\0'; + string_list_add_item(&names,temp); + } + fclose(fi); + } + else + { + string_list_add_item(&names,"Credits were not found!"); + string_list_add_item(&names,"Shame on the guy, who"); + string_list_add_item(&names,"forgot to include them"); + string_list_add_item(&names,"in your SuperTux distribution."); + } + + + timer_init(&timer, SDL_GetTicks()); + timer_start(&timer, 50); + + scroll = 0; + speed = 2; + done = 0; + + n = d = 0; + + length = names.num_items; + + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + + while(done == 0) + { + /* in case of input, exit */ + while(SDL_PollEvent(&event)) + switch(event.type) + { + case SDL_KEYDOWN: + switch(event.key.keysym.sym) + { + case SDLK_UP: + speed -= SPEED; + break; + case SDLK_DOWN: + speed += SPEED; + break; + case SDLK_SPACE: + case SDLK_RETURN: + if(speed >= 0) + scroll += SCROLL; + break; + case SDLK_ESCAPE: + done = 1; + break; + default: + break; + } + break; + case SDL_QUIT: + done = 1; + break; + default: + break; + } + + if(speed > MAX_VEL) + speed = MAX_VEL; + else if(speed < -MAX_VEL) + speed = -MAX_VEL; + + /* draw the credits */ + + draw_background(); + + text_drawf(&white_big_text, "- Credits -", 0, screen->h-scroll, A_HMIDDLE, A_TOP, 2, NO_UPDATE); + + for(i = 0, n = 0, d = 0; i < length; i++,n++,d++) + { + if(names.item[i] == "") + n--; + else + { + if(names.item[i][0] == ' ') + text_drawf(&white_small_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll-10, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + else if(names.item[i][0] == ' ') + text_drawf(&white_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + else if(names.item[i+1][0] == '-' || names.item[i][0] == '-') + text_drawf(&white_big_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 3, NO_UPDATE); + else + text_drawf(&blue_text, names.item[i], 0, 60+screen->h+(n*18)+(d*18)-scroll, A_HMIDDLE, A_TOP, 1, NO_UPDATE); + } + } + + + texture_draw_part(&bkg_title, 0, 0, 0, 0, 640, 130, NO_UPDATE); + + flipscreen(); + + if(60+screen->h+(n*18)+(d*18)-scroll < 0 && 20+60+screen->h+(n*18)+(d*18)-scroll < 0) + done = 1; + + scroll += speed; + if(scroll < 0) + scroll = 0; + + SDL_Delay(35); + + if(timer_get_left(&timer) < 0) + { + frame++; + timer_start(&timer, 50); + } + } + string_list_free(&names); + + SDL_EnableKeyRepeat(0, 0); // disables key repeating + show_menu = 1; + menu_set_current(&main_menu); +} diff --git a/src/type.c b/src/type.c deleted file mode 100644 index 3b0e1a453..000000000 --- a/src/type.c +++ /dev/null @@ -1,117 +0,0 @@ -// -// C Implementation: type -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "SDL_image.h" -#include "string.h" -#include "stdlib.h" -#include "setup.h" -#include "globals.h" -#include "screen.h" -#include "defines.h" -#include "type.h" -#include "scene.h" - -void string_list_init(string_list_type* pstring_list) -{ - pstring_list->num_items = 0; - pstring_list->active_item = -1; - pstring_list->item = NULL; -} - -char* string_list_active(string_list_type* pstring_list) -{ - if(pstring_list == NULL) - return ""; - - if(pstring_list->active_item != -1) - return pstring_list->item[pstring_list->active_item]; - else - return ""; -} - -void string_list_add_item(string_list_type* pstring_list, char* str) -{ - char *pnew_string; - pnew_string = (char*) malloc(sizeof(char)*(strlen(str)+1)); - strcpy(pnew_string,str); - ++pstring_list->num_items; - pstring_list->item = (char**) realloc(pstring_list->item,sizeof(char**)*pstring_list->num_items); - pstring_list->item[pstring_list->num_items-1] = pnew_string; - if(pstring_list->active_item == -1) - pstring_list->active_item = 0; -} - -void string_list_copy(string_list_type* pstring_list, string_list_type pstring_list_orig) -{ - int i; - string_list_free(pstring_list); - for(i = 0; i < pstring_list_orig.num_items; ++i) - string_list_add_item(pstring_list,pstring_list_orig.item[i]); -} - -int string_list_find(string_list_type* pstring_list, char* str) -{ - int i; - for(i = 0; i < pstring_list->num_items; ++i) - { - if(strcmp(pstring_list->item[i],str) == 0) - { - return i; - } - } - return -1; -} - -void string_list_sort(string_list_type* pstring_list) -{ - int i,j,y; - short int sorter[pstring_list->num_items]; - - for(j = 0; j < pstring_list->num_items; ++j) - for(i = 0; i < pstring_list->num_items-1; ++i) - { - - y = strcmp(pstring_list->item[i],pstring_list->item[i+1]); - if(y == 0) - { - continue; - } - else if(y < 0) - { - continue; - } - else if(y > 0) - { - char* char_pointer; - char_pointer = pstring_list->item[i]; - pstring_list->item[i] = pstring_list->item[i+1]; - pstring_list->item[i+1] = char_pointer; - continue; - } - - } - -} - -void string_list_free(string_list_type* pstring_list) -{ - if(pstring_list != NULL) - { - int i; - for(i=0; i < pstring_list->num_items; ++i) - free(pstring_list->item[i]); - free(pstring_list->item); - pstring_list->item = NULL; - pstring_list->num_items = 0; - pstring_list->active_item = -1; - } -} diff --git a/src/type.cpp b/src/type.cpp new file mode 100644 index 000000000..3b0e1a453 --- /dev/null +++ b/src/type.cpp @@ -0,0 +1,117 @@ +// +// C Implementation: type +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "SDL_image.h" +#include "string.h" +#include "stdlib.h" +#include "setup.h" +#include "globals.h" +#include "screen.h" +#include "defines.h" +#include "type.h" +#include "scene.h" + +void string_list_init(string_list_type* pstring_list) +{ + pstring_list->num_items = 0; + pstring_list->active_item = -1; + pstring_list->item = NULL; +} + +char* string_list_active(string_list_type* pstring_list) +{ + if(pstring_list == NULL) + return ""; + + if(pstring_list->active_item != -1) + return pstring_list->item[pstring_list->active_item]; + else + return ""; +} + +void string_list_add_item(string_list_type* pstring_list, char* str) +{ + char *pnew_string; + pnew_string = (char*) malloc(sizeof(char)*(strlen(str)+1)); + strcpy(pnew_string,str); + ++pstring_list->num_items; + pstring_list->item = (char**) realloc(pstring_list->item,sizeof(char**)*pstring_list->num_items); + pstring_list->item[pstring_list->num_items-1] = pnew_string; + if(pstring_list->active_item == -1) + pstring_list->active_item = 0; +} + +void string_list_copy(string_list_type* pstring_list, string_list_type pstring_list_orig) +{ + int i; + string_list_free(pstring_list); + for(i = 0; i < pstring_list_orig.num_items; ++i) + string_list_add_item(pstring_list,pstring_list_orig.item[i]); +} + +int string_list_find(string_list_type* pstring_list, char* str) +{ + int i; + for(i = 0; i < pstring_list->num_items; ++i) + { + if(strcmp(pstring_list->item[i],str) == 0) + { + return i; + } + } + return -1; +} + +void string_list_sort(string_list_type* pstring_list) +{ + int i,j,y; + short int sorter[pstring_list->num_items]; + + for(j = 0; j < pstring_list->num_items; ++j) + for(i = 0; i < pstring_list->num_items-1; ++i) + { + + y = strcmp(pstring_list->item[i],pstring_list->item[i+1]); + if(y == 0) + { + continue; + } + else if(y < 0) + { + continue; + } + else if(y > 0) + { + char* char_pointer; + char_pointer = pstring_list->item[i]; + pstring_list->item[i] = pstring_list->item[i+1]; + pstring_list->item[i+1] = char_pointer; + continue; + } + + } + +} + +void string_list_free(string_list_type* pstring_list) +{ + if(pstring_list != NULL) + { + int i; + for(i=0; i < pstring_list->num_items; ++i) + free(pstring_list->item[i]); + free(pstring_list->item); + pstring_list->item = NULL; + pstring_list->num_items = 0; + pstring_list->active_item = -1; + } +} diff --git a/src/world.c b/src/world.c deleted file mode 100644 index 7e7c4e6ea..000000000 --- a/src/world.c +++ /dev/null @@ -1,192 +0,0 @@ -// -// C Implementation: world -// -// Description: -// -// -// Author: Tobias Glaesser , (C) 2004 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include -#include -#include "globals.h" -#include "scene.h" -#include "screen.h" -#include "defines.h" -#include "world.h" - -texture_type img_distro[4]; - -void bouncy_distro_init(bouncy_distro_type* pbouncy_distro, float x, float y) -{ - pbouncy_distro->base.alive = YES; - pbouncy_distro->base.x = x; - pbouncy_distro->base.y = y; - pbouncy_distro->base.ym = -2; -} - -void bouncy_distro_action(bouncy_distro_type* pbouncy_distro) -{ - if (pbouncy_distro->base.alive) - { - pbouncy_distro->base.y = pbouncy_distro->base.y + pbouncy_distro->base.ym * frame_ratio; - - pbouncy_distro->base.ym += 0.1 * frame_ratio; - - if (pbouncy_distro->base.ym >= 0) - pbouncy_distro->base.alive = NO; - } -} - -void bouncy_distro_draw(bouncy_distro_type* pbouncy_distro) -{ - if (pbouncy_distro->base.alive) - { - texture_draw(&img_distro[0], - pbouncy_distro->base.x - scroll_x, - pbouncy_distro->base.y, - NO_UPDATE); - } -} - -void broken_brick_init(broken_brick_type* pbroken_brick, float x, float y, float xm, float ym) -{ - pbroken_brick->base.alive = YES; - pbroken_brick->base.x = x; - pbroken_brick->base.y = y; - pbroken_brick->base.xm = xm; - pbroken_brick->base.ym = ym; - timer_init(&pbroken_brick->timer,YES); - timer_start(&pbroken_brick->timer,200); -} - -void broken_brick_action(broken_brick_type* pbroken_brick) -{ - if (pbroken_brick->base.alive) - { - pbroken_brick->base.x = pbroken_brick->base.x + pbroken_brick->base.xm * frame_ratio; - pbroken_brick->base.y = pbroken_brick->base.y + pbroken_brick->base.ym * frame_ratio; - - if (!timer_check(&pbroken_brick->timer)) - pbroken_brick->base.alive = NO; - } -} - -void broken_brick_draw(broken_brick_type* pbroken_brick) -{ -SDL_Rect src, dest; - if (pbroken_brick->base.alive) - { - src.x = rand() % 16; - src.y = rand() % 16; - src.w = 16; - src.h = 16; - - dest.x = (int)(pbroken_brick->base.x - scroll_x); - dest.y = (int)pbroken_brick->base.y; - dest.w = 16; - dest.h = 16; - - texture_draw_part(&img_brick[0],src.x,src.y,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); - } -} - -void bouncy_brick_init(bouncy_brick_type* pbouncy_brick, float x, float y) -{ - pbouncy_brick->base.alive = YES; - pbouncy_brick->base.x = x; - pbouncy_brick->base.y = y; - pbouncy_brick->offset = 0; - pbouncy_brick->offset_m = -BOUNCY_BRICK_SPEED; - pbouncy_brick->shape = shape(x, y); -} - -void bouncy_brick_action(bouncy_brick_type* pbouncy_brick) -{ - - if (pbouncy_brick->base.alive) - { - - pbouncy_brick->offset = (pbouncy_brick->offset + - pbouncy_brick->offset_m * frame_ratio); - - /* Go back down? */ - - if (pbouncy_brick->offset < -BOUNCY_BRICK_MAX_OFFSET) - pbouncy_brick->offset_m = BOUNCY_BRICK_SPEED; - - - /* Stop bouncing? */ - - if (pbouncy_brick->offset >= 0) - pbouncy_brick->base.alive = NO; - } -} - -void bouncy_brick_draw(bouncy_brick_type* pbouncy_brick) -{ - int s; - SDL_Rect dest; - - if (pbouncy_brick->base.alive) - { - if (pbouncy_brick->base.x >= scroll_x - 32 && - pbouncy_brick->base.x <= scroll_x + screen->w) - { - dest.x = (int)(pbouncy_brick->base.x - scroll_x); - dest.y = (int)pbouncy_brick->base.y; - dest.w = 32; - dest.h = 32; - - if(current_level.bkgd_image[0] == '\0') - { - fillrect(pbouncy_brick->base.x - scroll_x,pbouncy_brick->base.y,32,32,current_level.bkgd_red,current_level.bkgd_green, - current_level.bkgd_blue,0); - } - else - { - s = (int)scroll_x / 30; - texture_draw_part(&img_bkgd,dest.x + s,dest.y,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); - } - - drawshape(pbouncy_brick->base.x - scroll_x, - pbouncy_brick->base.y + pbouncy_brick->offset, - pbouncy_brick->shape); - } - } -} - -void floating_score_init(floating_score_type* pfloating_score, float x, float y, int s) -{ - pfloating_score->base.alive = YES; - pfloating_score->base.x = x; - pfloating_score->base.y = y - 16; - timer_init(&pfloating_score->timer,YES); - timer_start(&pfloating_score->timer,1000); - pfloating_score->value = s; -} - -void floating_score_action(floating_score_type* pfloating_score) -{ - if (pfloating_score->base.alive) - { - pfloating_score->base.y = pfloating_score->base.y - 2 * frame_ratio; - - if(!timer_check(&pfloating_score->timer)) - pfloating_score->base.alive = NO; - } -} - -void floating_score_draw(floating_score_type* pfloating_score) -{ - if (pfloating_score->base.alive) - { - char str[10]; - sprintf(str, "%d", pfloating_score->value); - text_draw(&gold_text, str, (int)pfloating_score->base.x + 16 - strlen(str) * 8, (int)pfloating_score->base.y, 1, NO_UPDATE); - } -} - diff --git a/src/world.cpp b/src/world.cpp new file mode 100644 index 000000000..7e7c4e6ea --- /dev/null +++ b/src/world.cpp @@ -0,0 +1,192 @@ +// +// C Implementation: world +// +// Description: +// +// +// Author: Tobias Glaesser , (C) 2004 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include +#include +#include "globals.h" +#include "scene.h" +#include "screen.h" +#include "defines.h" +#include "world.h" + +texture_type img_distro[4]; + +void bouncy_distro_init(bouncy_distro_type* pbouncy_distro, float x, float y) +{ + pbouncy_distro->base.alive = YES; + pbouncy_distro->base.x = x; + pbouncy_distro->base.y = y; + pbouncy_distro->base.ym = -2; +} + +void bouncy_distro_action(bouncy_distro_type* pbouncy_distro) +{ + if (pbouncy_distro->base.alive) + { + pbouncy_distro->base.y = pbouncy_distro->base.y + pbouncy_distro->base.ym * frame_ratio; + + pbouncy_distro->base.ym += 0.1 * frame_ratio; + + if (pbouncy_distro->base.ym >= 0) + pbouncy_distro->base.alive = NO; + } +} + +void bouncy_distro_draw(bouncy_distro_type* pbouncy_distro) +{ + if (pbouncy_distro->base.alive) + { + texture_draw(&img_distro[0], + pbouncy_distro->base.x - scroll_x, + pbouncy_distro->base.y, + NO_UPDATE); + } +} + +void broken_brick_init(broken_brick_type* pbroken_brick, float x, float y, float xm, float ym) +{ + pbroken_brick->base.alive = YES; + pbroken_brick->base.x = x; + pbroken_brick->base.y = y; + pbroken_brick->base.xm = xm; + pbroken_brick->base.ym = ym; + timer_init(&pbroken_brick->timer,YES); + timer_start(&pbroken_brick->timer,200); +} + +void broken_brick_action(broken_brick_type* pbroken_brick) +{ + if (pbroken_brick->base.alive) + { + pbroken_brick->base.x = pbroken_brick->base.x + pbroken_brick->base.xm * frame_ratio; + pbroken_brick->base.y = pbroken_brick->base.y + pbroken_brick->base.ym * frame_ratio; + + if (!timer_check(&pbroken_brick->timer)) + pbroken_brick->base.alive = NO; + } +} + +void broken_brick_draw(broken_brick_type* pbroken_brick) +{ +SDL_Rect src, dest; + if (pbroken_brick->base.alive) + { + src.x = rand() % 16; + src.y = rand() % 16; + src.w = 16; + src.h = 16; + + dest.x = (int)(pbroken_brick->base.x - scroll_x); + dest.y = (int)pbroken_brick->base.y; + dest.w = 16; + dest.h = 16; + + texture_draw_part(&img_brick[0],src.x,src.y,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); + } +} + +void bouncy_brick_init(bouncy_brick_type* pbouncy_brick, float x, float y) +{ + pbouncy_brick->base.alive = YES; + pbouncy_brick->base.x = x; + pbouncy_brick->base.y = y; + pbouncy_brick->offset = 0; + pbouncy_brick->offset_m = -BOUNCY_BRICK_SPEED; + pbouncy_brick->shape = shape(x, y); +} + +void bouncy_brick_action(bouncy_brick_type* pbouncy_brick) +{ + + if (pbouncy_brick->base.alive) + { + + pbouncy_brick->offset = (pbouncy_brick->offset + + pbouncy_brick->offset_m * frame_ratio); + + /* Go back down? */ + + if (pbouncy_brick->offset < -BOUNCY_BRICK_MAX_OFFSET) + pbouncy_brick->offset_m = BOUNCY_BRICK_SPEED; + + + /* Stop bouncing? */ + + if (pbouncy_brick->offset >= 0) + pbouncy_brick->base.alive = NO; + } +} + +void bouncy_brick_draw(bouncy_brick_type* pbouncy_brick) +{ + int s; + SDL_Rect dest; + + if (pbouncy_brick->base.alive) + { + if (pbouncy_brick->base.x >= scroll_x - 32 && + pbouncy_brick->base.x <= scroll_x + screen->w) + { + dest.x = (int)(pbouncy_brick->base.x - scroll_x); + dest.y = (int)pbouncy_brick->base.y; + dest.w = 32; + dest.h = 32; + + if(current_level.bkgd_image[0] == '\0') + { + fillrect(pbouncy_brick->base.x - scroll_x,pbouncy_brick->base.y,32,32,current_level.bkgd_red,current_level.bkgd_green, + current_level.bkgd_blue,0); + } + else + { + s = (int)scroll_x / 30; + texture_draw_part(&img_bkgd,dest.x + s,dest.y,dest.x,dest.y,dest.w,dest.h,NO_UPDATE); + } + + drawshape(pbouncy_brick->base.x - scroll_x, + pbouncy_brick->base.y + pbouncy_brick->offset, + pbouncy_brick->shape); + } + } +} + +void floating_score_init(floating_score_type* pfloating_score, float x, float y, int s) +{ + pfloating_score->base.alive = YES; + pfloating_score->base.x = x; + pfloating_score->base.y = y - 16; + timer_init(&pfloating_score->timer,YES); + timer_start(&pfloating_score->timer,1000); + pfloating_score->value = s; +} + +void floating_score_action(floating_score_type* pfloating_score) +{ + if (pfloating_score->base.alive) + { + pfloating_score->base.y = pfloating_score->base.y - 2 * frame_ratio; + + if(!timer_check(&pfloating_score->timer)) + pfloating_score->base.alive = NO; + } +} + +void floating_score_draw(floating_score_type* pfloating_score) +{ + if (pfloating_score->base.alive) + { + char str[10]; + sprintf(str, "%d", pfloating_score->value); + text_draw(&gold_text, str, (int)pfloating_score->base.x + 16 - strlen(str) * 8, (int)pfloating_score->base.y, 1, NO_UPDATE); + } +} +