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
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])
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])
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
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
# 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)
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 #
+++ /dev/null
-//
-// C Implementation: badguy
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de> & 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;
- }
-
-}
--- /dev/null
+//
+// C Implementation: badguy
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de> & 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;
+ }
+
+}
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <stdio.h>
-#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<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;) /* Join these two to one loop */
- if ((*ap++ >> 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<bstripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;)
- if ((*ap++ >> 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;i<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;)
- if (*ap++ & *bp++)
- return 1;
- a_entry += a->h;
- 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;i<astripes;i++)
- {
- 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;
- }
- 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;i<bstripes;i++)
- {
- 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;
- }
- 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;i<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- {
- if (*ap & *bp)
- {
- *y = (ap - a->bits) % 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<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- count += bitcount(((*ap >> 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<bstripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- count += bitcount(((*ap >> 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;i<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;)
- count += bitcount(*ap++ & *bp++);
-
- a_entry += a->h;
- 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;i<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- *ap |= (*bp << shift);
- a_entry += a->h;
- 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;i<bstripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- *ap |= (*bp << shift);
- a_entry += a->h;
- 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;i<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- {
- *ap |= *bp;
- }
- a_entry += a->h;
- 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<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- *bp |= (*ap >> 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;
- }
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- *bp |= (*ap >> shift);
- return;
- }
- else /* zig-zag */
- {
- for (i=0;i<bstripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- *bp |= (*ap >> 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;i<astripes;i++)
- {
- for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
- {
- *bp |= *ap;
- }
- a_entry += a->h;
- a_end += a->h;
- b_entry += b->h;
- }
- return;
- }
- }
-}
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <stdio.h>
+#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<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;) /* Join these two to one loop */
+ if ((*ap++ >> 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<bstripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;)
+ if ((*ap++ >> 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;i<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;)
+ if (*ap++ & *bp++)
+ return 1;
+ a_entry += a->h;
+ 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;i<astripes;i++)
+ {
+ 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;
+ }
+ 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;i<bstripes;i++)
+ {
+ 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;
+ }
+ 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;i<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ {
+ if (*ap & *bp)
+ {
+ *y = (ap - a->bits) % 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<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ count += bitcount(((*ap >> 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<bstripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ count += bitcount(((*ap >> 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;i<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;)
+ count += bitcount(*ap++ & *bp++);
+
+ a_entry += a->h;
+ 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;i<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ *ap |= (*bp << shift);
+ a_entry += a->h;
+ 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;i<bstripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ *ap |= (*bp << shift);
+ a_entry += a->h;
+ 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;i<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ {
+ *ap |= *bp;
+ }
+ a_entry += a->h;
+ 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<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ *bp |= (*ap >> 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;
+ }
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ *bp |= (*ap >> shift);
+ return;
+ }
+ else /* zig-zag */
+ {
+ for (i=0;i<bstripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ *bp |= (*ap >> 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;i<astripes;i++)
+ {
+ for (ap = a_entry,bp = b_entry;ap < a_end;ap++,bp++)
+ {
+ *bp |= *ap;
+ }
+ a_entry += a->h;
+ a_end += a->h;
+ b_entry += b->h;
+ }
+ return;
+ }
+ }
+}
+++ /dev/null
-//
-// C Implementation: button
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include <string.h>
-#include <stdlib.h>
-#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;
-
-}
-
--- /dev/null
+//
+// C Implementation: button
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <string.h>
+#include <stdlib.h>
+#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;
+
+}
+
+++ /dev/null
-//
-// C Implementation: collision
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (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);
- }
-
- }
- }
-
-}
-
-
--- /dev/null
+//
+// C Implementation: collision
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (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);
+ }
+
+ }
+ }
+
+}
+
+
+++ /dev/null
-/*
- 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <time.h>
-#include <SDL.h>
-
-#ifdef LINUX
-#include <pwd.h>
-#include <sys/types.h>
-#include <ctype.h>
-#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);
-
-}
-
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <SDL.h>
+
+#ifdef LINUX
+#include <pwd.h>
+#include <sys/types.h>
+#include <ctype.h>
+#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);
+
+}
+
+++ /dev/null
-//
-// C Implementation: globals
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (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
-
-
--- /dev/null
+//
+// C Implementation: globals
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (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
+
+
+++ /dev/null
-/*
-
- by Adam Czachorowski
- gislan@o2.pl
-
-*/
-
-/* Open the highscore file: */
-
-#include <string.h>
-#include <stdlib.h>
-
-#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);
- }
-}
--- /dev/null
+/*
+
+ by Adam Czachorowski
+ gislan@o2.pl
+
+*/
+
+/* Open the highscore file: */
+
+#include <string.h>
+#include <stdlib.h>
+
+#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);
+ }
+}
+++ /dev/null
-/*
- intro.c
-
- Super Tux - Intro Screen
-
- by Bill Kendrick
- bill@newbreedsoftware.com
- http://www.newbreedsoftware.com/supertux/
-
- April 11, 2000 - March 15, 2004
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <SDL.h>
-#include <SDL_image.h>
-
-#ifdef LINUX
-#include <pwd.h>
-#include <sys/types.h>
-#include <ctype.h>
-#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);
-}
--- /dev/null
+/*
+ intro.c
+
+ Super Tux - Intro Screen
+
+ by Bill Kendrick
+ bill@newbreedsoftware.com
+ http://www.newbreedsoftware.com/supertux/
+
+ April 11, 2000 - March 15, 2004
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <SDL_image.h>
+
+#ifdef LINUX
+#include <pwd.h>
+#include <sys/types.h>
+#include <ctype.h>
+#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);
+}
+++ /dev/null
-//
-// C Implementation: level
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2003
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#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);
-}
--- /dev/null
+//
+// C Implementation: level
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2003
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#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);
+}
+++ /dev/null
-/***************************************************************************
- * *
- * 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 <rick2@aeiou.pt>
- Tobias Glaesser <tobi.web@gmx.de> */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <SDL.h>
-#include <SDL_image.h>
-#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);
- }
-}
--- /dev/null
+/***************************************************************************
+ * *
+ * 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 <rick2@aeiou.pt>
+ Tobias Glaesser <tobi.web@gmx.de> */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <SDL_image.h>
+#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);
+ }
+}
+++ /dev/null
-/* $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 <assert.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <lispreader.h>
-
-#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("#<eof>", out);
- break;
-
- case LISP_TYPE_PARSE_ERROR :
- fputs("#<error>", 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);
- }
-}
--- /dev/null
+/* $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 <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lispreader.h>
+
+#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("#<eof>", out);
+ break;
+
+ case LISP_TYPE_PARSE_ERROR :
+ fputs("#<error>", 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);
+ }
+}
+++ /dev/null
-/*
- 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 <pwd.h>
-#include <sys/types.h>
-#include <ctype.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#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*/
-}
-
--- /dev/null
+/*
+ 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 <pwd.h>
+#include <sys/types.h>
+#include <ctype.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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*/
+}
+
+++ /dev/null
-//
-// C Implementation: physic
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include <stdio.h>
-#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;
-}
-
-
--- /dev/null
+//
+// C Implementation: physic
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <stdio.h>
+#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;
+}
+
+
+++ /dev/null
-//
-// C Implementation: player/tux
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de> & 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);
- }
-}
--- /dev/null
+//
+// C Implementation: player/tux
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de> & 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);
+ }
+}
+++ /dev/null
-//
-// C Implementation: scene
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include <stdlib.h>
-#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);
- }
-}
-
--- /dev/null
+//
+// C Implementation: scene
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <stdlib.h>
+#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);
+ }
+}
+
+++ /dev/null
-/*
- screen.c
-
- Super Tux - Screen Functions
-
- by Bill Kendrick
- bill@newbreedsoftware.com
- http://www.newbreedsoftware.com/supertux/
-
- April 11, 2000 - March 15, 2004
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <SDL.h>
-#include <SDL_image.h>
-
-#ifdef LINUX
-#include <pwd.h>
-#include <sys/types.h>
-#include <ctype.h>
-#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);
-}
-
--- /dev/null
+/*
+ screen.c
+
+ Super Tux - Screen Functions
+
+ by Bill Kendrick
+ bill@newbreedsoftware.com
+ http://www.newbreedsoftware.com/supertux/
+
+ April 11, 2000 - March 15, 2004
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <SDL_image.h>
+
+#ifdef LINUX
+#include <pwd.h>
+#include <sys/types.h>
+#include <ctype.h>
+#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);
+}
+
+++ /dev/null
-/*
- setup.c
-
- Super Tux - Setup
-
- by Bill Kendrick
- bill@newbreedsoftware.com
- http://www.newbreedsoftware.com/supertux/
-
- April 11, 2000 - March 15, 2004
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <SDL.h>
-#include <SDL_image.h>
-#ifndef NOOPENGL
-#include <SDL_opengl.h>
-#endif
-
-#ifdef LINUX
-#include <pwd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <ctype.h>
-#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);
-}
-
--- /dev/null
+/*
+ setup.c
+
+ Super Tux - Setup
+
+ by Bill Kendrick
+ bill@newbreedsoftware.com
+ http://www.newbreedsoftware.com/supertux/
+
+ April 11, 2000 - March 15, 2004
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <SDL_image.h>
+#ifndef NOOPENGL
+#include <SDL_opengl.h>
+#endif
+
+#ifdef LINUX
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <ctype.h>
+#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);
+}
+
+++ /dev/null
-/*
- 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 <SDL_mixer.h>
-
-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
--- /dev/null
+/*
+ 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 <SDL_mixer.h>
+
+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
+++ /dev/null
-//
-// C Implementation: special
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de> & 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;
- }
-}
-
--- /dev/null
+//
+// C Implementation: special
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de> & 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;
+ }
+}
+
+++ /dev/null
-/*
- supertux.c
-
- Super Tux
-
- by Bill Kendrick & Tobias Glaesser <tobi.web@gmx.de>
- 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);
-}
--- /dev/null
+/*
+ supertux.c
+
+ Super Tux
+
+ by Bill Kendrick & Tobias Glaesser <tobi.web@gmx.de>
+ 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);
+}
+++ /dev/null
-//
-// C Implementation: text
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include <stdlib.h>
-#include <string.h>
-#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);
-}
--- /dev/null
+//
+// C Implementation: text
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <stdlib.h>
+#include <string.h>
+#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);
+}
+++ /dev/null
-//
-// C Implementation: texture
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (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);
-}
-
--- /dev/null
+//
+// C Implementation: texture
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (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);
+}
+
+++ /dev/null
-//
-// C Implementation: timer
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (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;
-
-}
-
--- /dev/null
+//
+// C Implementation: timer
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (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;
+
+}
+
+++ /dev/null
-/*
- title.c
-
- Super Tux - Title Screen
-
- by Bill Kendrick
- bill@newbreedsoftware.com
- http://www.newbreedsoftware.com/supertux/
-
- April 11, 2000 - March 15, 2004
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <SDL.h>
-#include <SDL_image.h>
-
-#ifdef LINUX
-#include <pwd.h>
-#include <sys/types.h>
-#include <ctype.h>
-#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);
-}
--- /dev/null
+/*
+ title.c
+
+ Super Tux - Title Screen
+
+ by Bill Kendrick
+ bill@newbreedsoftware.com
+ http://www.newbreedsoftware.com/supertux/
+
+ April 11, 2000 - March 15, 2004
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <SDL_image.h>
+
+#ifdef LINUX
+#include <pwd.h>
+#include <sys/types.h>
+#include <ctype.h>
+#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);
+}
+++ /dev/null
-//
-// C Implementation: type
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (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;
- }
-}
--- /dev/null
+//
+// C Implementation: type
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (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;
+ }
+}
+++ /dev/null
-//
-// C Implementation: world
-//
-// Description:
-//
-//
-// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
-//
-// Copyright: See COPYING file that comes with this distribution
-//
-//
-
-#include <stdlib.h>
-#include <string.h>
-#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);
- }
-}
-
--- /dev/null
+//
+// C Implementation: world
+//
+// Description:
+//
+//
+// Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include <stdlib.h>
+#include <string.h>
+#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);
+ }
+}
+