// $Id$
//
-// Pingus - A free Lemmings clone
-// Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
+// SuperTux - A Jump'n Run
+// Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
#include <iostream>
#include <vector>
#include <assert.h>
+#include "globals.h"
#include "texture.h"
#include "screen.h"
#include "lispreader.h"
#include "gameloop.h"
+#include "setup.h"
#include "worldmap.h"
namespace WorldMapNS {
TileManager::TileManager()
{
- lisp_stream_t stream;
- FILE* in = fopen(DATA_PREFIX "images/worldmap/antarctica.scm", "r");
- assert(in);
- lisp_stream_init_file (&stream, in);
- lisp_object_t* root_obj = lisp_read (&stream);
-
+ std::string stwt_filename = datadir + "images/worldmap/antarctica.stwt";
+ lisp_object_t* root_obj = lisp_read_from_file(stwt_filename);
+
+ if (!root_obj)
+ st_abort("Couldn't load file", stwt_filename);
+
if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-worldmap-tiles") == 0)
{
lisp_object_t* cur = lisp_cdr(root_obj);
reader.read_string("image", &filename);
texture_load(&tile->sprite,
- const_cast<char*>((std::string(DATA_PREFIX "/images/worldmap/") + filename).c_str()),
+ datadir + "/images/worldmap/" + filename,
USE_ALPHA);
- if (id >= tiles.size())
+ if (id >= int(tiles.size()))
tiles.resize(id+1);
tiles[id] = tile;
Tile*
TileManager::get(int i)
{
- assert(i >=0 && i < tiles.size());
+ assert(i >=0 && i < int(tiles.size()));
return tiles[i];
}
+Tux::Tux(WorldMap* worldmap_)
+ : worldmap(worldmap_)
+{
+ texture_load(&sprite, datadir + "/images/worldmap/tux.png", USE_ALPHA);
+ offset = 0;
+ moving = false;
+ tile_pos.x = 0;
+ tile_pos.y = 0;
+ direction = NONE;
+ input_direction = NONE;
+}
+
+void
+Tux::draw()
+{
+ float x = tile_pos.x * 32;
+ float y = tile_pos.y * 32;
+
+ switch(direction)
+ {
+ case WEST:
+ x -= offset - 32;
+ break;
+ case EAST:
+ x += offset - 32;
+ break;
+ case NORTH:
+ y -= offset - 32;
+ break;
+ case SOUTH:
+ y += offset - 32;
+ break;
+ case NONE:
+ break;
+ }
+
+ texture_draw(&sprite, (int)x, (int)y, NO_UPDATE);
+}
+
+void
+Tux::stop()
+{
+ offset = 0;
+ direction = NONE;
+ moving = false;
+}
+
+void
+Tux::update(float delta)
+{
+ if (!moving)
+ {
+ if (input_direction != NONE)
+ { // We got a new direction, so lets start walking when possible
+ Point next_tile;
+ if (worldmap->path_ok(input_direction, tile_pos, &next_tile))
+ {
+ tile_pos = next_tile;
+ moving = true;
+ direction = input_direction;
+ }
+ }
+ }
+ else
+ {
+ // Let tux walk a few pixels (20 pixel/sec)
+ offset += 20.0f * delta;
+
+ if (offset > 32)
+ { // We reached the next tile, so we check what to do now
+ offset -= 32;
+
+ if (worldmap->at(tile_pos)->stop)
+ {
+ stop();
+ }
+ else
+ {
+ Point next_tile;
+ if (worldmap->path_ok(direction, tile_pos, &next_tile))
+ {
+ tile_pos = next_tile;
+ }
+ else
+ {
+ puts("Tilemap data is buggy");
+ stop();
+ }
+ }
+ }
+ }
+}
+
WorldMap::WorldMap()
{
+ tux = new Tux(this);
+
quit = false;
width = 20;
height = 15;
- tux_moving = false;
- texture_load(&tux_sprite, DATA_PREFIX "/images/worldmap/tux.png", USE_ALPHA);
- texture_load(&level_sprite, DATA_PREFIX "/images/worldmap/levelmarker.png", USE_ALPHA);
-
- tux_offset = 0;
-
- tux_tile_pos.x = 0;
- tux_tile_pos.y = 0;
+ texture_load(&level_sprite, datadir + "/images/worldmap/levelmarker.png", USE_ALPHA);
input_direction = NONE;
- tux_direction = NONE;
enter_level = false;
name = "<no name>";
WorldMap::~WorldMap()
{
+ delete tux;
}
void
WorldMap::load_map()
{
- lisp_stream_t stream;
- FILE* in = fopen(DATA_PREFIX "levels/default/worldmap.scm", "r");
- assert(in);
- lisp_stream_init_file (&stream, in);
- lisp_object_t* root_obj = lisp_read (&stream);
+ std::string filename = datadir + "levels/default/worldmap.stwm";
+
+ lisp_object_t* root_obj = lisp_read_from_file(filename);
+ if (!root_obj)
+ st_abort("Couldn't load file", filename);
if (strcmp(lisp_symbol(lisp_car(root_obj)), "supertux-worldmap") == 0)
{
SDL_Event event;
enter_level = false;
+ input_direction = NONE;
while (SDL_PollEvent(&event))
{
break;
case SDLK_LCTRL:
case SDLK_RETURN:
- if (!tux_moving)
- enter_level = true;
+ enter_level = true;
+ break;
+ default:
break;
}
break;
+
+ case SDL_JOYAXISMOTION:
+ switch(event.jaxis.axis)
+ {
+ case JOY_X:
+ if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
+ input_direction = WEST;
+ else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
+ input_direction = EAST;
+ break;
+ case JOY_Y:
+ if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
+ input_direction = SOUTH;
+ else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
+ input_direction = NORTH;
+ break;
+ }
+ break;
+
+ case SDL_JOYBUTTONDOWN:
+ if (event.jbutton.button == JOY_B)
+ enter_level = true;
+ break;
+
+ default:
+ break;
}
}
Uint8 *keystate = SDL_GetKeyState(NULL);
- input_direction = NONE;
-
if (keystate[SDLK_LEFT])
input_direction = WEST;
else if (keystate[SDLK_RIGHT])
input_direction = SOUTH;
}
+Point
+WorldMap::get_next_tile(Point pos, Direction direction)
+{
+ switch(direction)
+ {
+ case WEST:
+ pos.x -= 1;
+ break;
+ case EAST:
+ pos.x += 1;
+ break;
+ case NORTH:
+ pos.y -= 1;
+ break;
+ case SOUTH:
+ pos.y += 1;
+ break;
+ case NONE:
+ break;
+ }
+ return pos;
+}
+
+bool
+WorldMap::path_ok(Direction direction, Point old_pos, Point* new_pos)
+{
+ *new_pos = get_next_tile(old_pos, direction);
+
+ if (!(new_pos->x >= 0 && new_pos->x < width
+ && new_pos->y >= 0 && new_pos->y < height))
+ { // New position is outsite the tilemap
+ return false;
+ }
+ else
+ { // Check if we the tile allows us to go to new_pos
+ switch(direction)
+ {
+ case WEST:
+ return (at(old_pos)->west && at(*new_pos)->east);
+
+ case EAST:
+ return (at(old_pos)->east && at(*new_pos)->west);
+
+ case NORTH:
+ return (at(old_pos)->north && at(*new_pos)->south);
+
+ case SOUTH:
+ return (at(old_pos)->south && at(*new_pos)->north);
+
+ case NONE:
+ assert(!"path_ok() can't work if direction is NONE");
+ }
+ return false;
+ }
+}
+
void
WorldMap::update()
{
- float speed = 4.5;
-
- if (enter_level)
+ if (enter_level && !tux->is_moving())
{
for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
{
- if (i->x == tux_tile_pos.x &&
- i->y == tux_tile_pos.y)
+ if (i->x == tux->get_tile_pos().x &&
+ i->y == tux->get_tile_pos().y)
{
std::cout << "Enter the current level: " << i->name << std::endl;;
halt_music();
- gameloop(const_cast<char*>((DATA_PREFIX "levels/default/" + i->name).c_str()),
- 1, ST_GL_LOAD_LEVEL_FILE);
+ gameloop(const_cast<char*>((datadir + "levels/default/" + i->name).c_str()),
+ 1, ST_GL_LOAD_LEVEL_FILE);
play_music(song, 1);
break;
}
}
-
}
else
{
- if (!tux_moving)
- {
- // FIXME: Cleanup, seperate tux
- switch(input_direction)
- {
- case WEST:
- if (at(tux_tile_pos)->west)
- {
- tux_tile_pos.x -= 1;
- tux_moving = true;
- tux_direction = input_direction;
- }
- break;
- case EAST:
- if (at(tux_tile_pos)->east)
- {
- tux_tile_pos.x += 1;
- tux_moving = true;
- tux_direction = input_direction;
- }
- break;
- case NORTH:
- if (at(tux_tile_pos)->north)
- {
- tux_tile_pos.y -= 1;
- tux_moving = true;
- tux_direction = input_direction;
- }
- break;
- case SOUTH:
- if (at(tux_tile_pos)->south)
- {
- tux_tile_pos.y += 1;
- tux_moving = true;
- tux_direction = input_direction;
- }
- break;
- case NONE:
- tux_moving = false;
- tux_offset = 0;
- tux_direction = input_direction;
- break;
- }
- }
- else
- {
- tux_offset += speed;
-
- if (tux_offset > 32)
- {
- tux_offset -= 32;
-
- if (at(tux_tile_pos)->stop)
- {
- tux_direction = NONE;
- tux_moving = false;
- }
- else
- {
- // FIXME: Cleanup, seperate tux
- switch(tux_direction)
- {
- case WEST:
- if (at(tux_tile_pos)->west)
- tux_tile_pos.x -= 1;
- break;
- case EAST:
- if (at(tux_tile_pos)->east)
- tux_tile_pos.x += 1;
- break;
- case NORTH:
- if (at(tux_tile_pos)->north)
- tux_tile_pos.y -= 1;
- break;
- case SOUTH:
- if (at(tux_tile_pos)->south)
- tux_tile_pos.y += 1;
- break;
- }
- }
- }
- }
+ tux->set_direction(input_direction);
+ tux->update(0.33f);
}
}
Tile* tile = at(Point(x, y));
texture_draw(&tile->sprite, x*32, y*32, NO_UPDATE);
}
-
- float x = tux_tile_pos.x * 32;
- float y = tux_tile_pos.y * 32;
-
- switch(tux_direction)
- {
- case WEST:
- x -= tux_offset - 32;
- break;
- case EAST:
- x += tux_offset - 32;
- break;
- case NORTH:
- y -= tux_offset - 32;
- break;
- case SOUTH:
- y += tux_offset - 32;
- break;
- }
-
for(Levels::iterator i = levels.begin(); i != levels.end(); ++i)
{
texture_draw(&level_sprite, i->x*32, i->y*32, NO_UPDATE);
}
- texture_draw(&tux_sprite, (int)x, (int)y, NO_UPDATE);
+ tux->draw();
flipscreen();
}
{
quit = false;
- song = load_song(const_cast<char*>((DATA_PREFIX "/music/" + music).c_str()));
+ song = load_song(datadir + "/music/" + music);
play_music(song, 1);
while(!quit) {