mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-06 02:10:28 +00:00
ULTIMA1: Basic arrow movement is now working
This commit is contained in:
parent
b0219c7725
commit
ee65b99bd5
@ -49,6 +49,7 @@ MODULE_OBJS += \
|
||||
ultima1/actions/move.o \
|
||||
ultima1/core/map.o \
|
||||
ultima1/core/resources.o \
|
||||
ultima1/core/transports.o \
|
||||
ultima1/gfx/drawing_support.o \
|
||||
ultima1/gfx/game_view.o \
|
||||
ultima1/gfx/status.o \
|
||||
|
@ -108,6 +108,26 @@ Point Map::getViewportPosition(const Point &viewportSize) {
|
||||
return topLeft;
|
||||
}
|
||||
|
||||
void Map::shiftViewport(const Point &delta) {
|
||||
Point &topLeft = _viewportPos._topLeft;
|
||||
topLeft += delta;
|
||||
|
||||
if (_fixed) {
|
||||
// Shift the viewport, but constraining the map to fill up the screen
|
||||
topLeft.x = CLIP(topLeft.x, (int16)0, (int16)(width() - _viewportPos._size.x));
|
||||
topLeft.y = CLIP(topLeft.y, (int16)0, (int16)(height() - _viewportPos._size.y));
|
||||
} else {
|
||||
if (topLeft.x < 0)
|
||||
topLeft.x += width();
|
||||
else if (topLeft.x >= (int16)width())
|
||||
topLeft.x -= width();
|
||||
if (topLeft.y < 0)
|
||||
topLeft.y += height();
|
||||
else if (topLeft.y >= (int16)height())
|
||||
topLeft.y -= height();
|
||||
}
|
||||
}
|
||||
|
||||
void Map::getTileAt(const Point &pt, MapTile *tile) {
|
||||
// Get the base tile
|
||||
tile->_tileNum = _data[pt.y * _size.x + pt.x];
|
||||
|
@ -31,7 +31,7 @@ namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
enum Direction {
|
||||
DIR_UP = 1, DIR_DOWN = 2, DIR_LEFT = 3, DIR_RIGHT = 4
|
||||
DIR_LEFT = 1, DIR_RIGHT = 2, DIR_UP = 3, DIR_DOWN = 4
|
||||
};
|
||||
|
||||
class Game;
|
||||
@ -115,12 +115,13 @@ protected:
|
||||
byte _mapId; // The map Id
|
||||
Common::Array<MapWidgetPtr> _widgets; // Party, monsteres, transports, etc.
|
||||
Common::Array<int16> _data; // Data for the map
|
||||
Point _position; // Current position within the map
|
||||
ViewportPosition _viewportPos; // Viewport position
|
||||
public:
|
||||
Point _size; // X, Y size of the map
|
||||
Point _tilesPerOrigTile; // For enhanced modes, number of tiles per original game tile
|
||||
Point _position; // Current position within the map
|
||||
Direction _direction; // Current direction being faced in the underworld
|
||||
bool _fixed; // Town/city type maps that don't scroll as the player moves
|
||||
ViewportPosition _viewportPos; // Viewport position
|
||||
protected:
|
||||
/**
|
||||
* Gets a point relative to the current position
|
||||
@ -144,9 +145,9 @@ public:
|
||||
size_t height() const { return _size.y; }
|
||||
|
||||
/**
|
||||
* Load a given map
|
||||
* Return the current position
|
||||
*/
|
||||
virtual void loadMap(int mapId, uint videoMode);
|
||||
Point getPosition() const { return _position; }
|
||||
|
||||
/**
|
||||
* Set the position
|
||||
@ -158,6 +159,11 @@ public:
|
||||
*/
|
||||
Point getViewportPosition(const Point &viewportSize);
|
||||
|
||||
/**
|
||||
* Shifts the viewport by a given delta
|
||||
*/
|
||||
void shiftViewport(const Point &delta);
|
||||
|
||||
/**
|
||||
* Gets a tile at a given position
|
||||
*/
|
||||
@ -167,6 +173,11 @@ public:
|
||||
* Adds a widget to the map
|
||||
*/
|
||||
void addWidget(MapWidget *widget);
|
||||
|
||||
/**
|
||||
* Load a given map
|
||||
*/
|
||||
virtual void loadMap(int mapId, uint videoMode);
|
||||
};
|
||||
|
||||
} // End of namespace Shared
|
||||
|
@ -61,6 +61,10 @@ Map *TreeItem::getMap() {
|
||||
return getGameState()->_map;
|
||||
}
|
||||
|
||||
Gfx::VisualItem *TreeItem::getView() {
|
||||
return getRoot()->getView();
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::getLastChild() const {
|
||||
if (!_firstChild)
|
||||
return nullptr;
|
||||
|
@ -28,6 +28,10 @@
|
||||
namespace Ultima {
|
||||
namespace Shared {
|
||||
|
||||
namespace Gfx {
|
||||
class VisualItem;
|
||||
} // End of namespace Gfx
|
||||
|
||||
class Game;
|
||||
class GameManager;
|
||||
class GameState;
|
||||
@ -108,6 +112,11 @@ public:
|
||||
*/
|
||||
Map *getMap();
|
||||
|
||||
/**
|
||||
* Returns the currently active game view
|
||||
*/
|
||||
Gfx::VisualItem *getView();
|
||||
|
||||
/**
|
||||
* Get the next sibling
|
||||
*/
|
||||
|
@ -251,6 +251,16 @@ MESSAGE1(CFrameMsg, uint, ticks, 0);
|
||||
*/
|
||||
MESSAGE1(CMoveMsg, int, direction, 0);
|
||||
|
||||
/**
|
||||
* Adds text strings to the status area
|
||||
*/
|
||||
MESSAGE1(CStatusMsg, Common::String, text, "");
|
||||
|
||||
/**
|
||||
* Signals a sound effect
|
||||
*/
|
||||
MESSAGE1(CSoundEffectMsg, uint, effectNum, 0);
|
||||
|
||||
} // End of namespace Shared
|
||||
} // End of namespace Ultima
|
||||
|
||||
|
@ -21,6 +21,11 @@
|
||||
*/
|
||||
|
||||
#include "ultima/ultima1/actions/action.h"
|
||||
#include "ultima/ultima1/game.h"
|
||||
#include "ultima/ultima1/core/map.h"
|
||||
#include "ultima/ultima1/core/resources.h"
|
||||
#include "ultima/shared/engine/messages.h"
|
||||
#include "ultima/shared/gfx/visual_item.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima1 {
|
||||
@ -31,6 +36,23 @@ Action::Action(TreeItem *parent) : Shared::TreeItem() {
|
||||
addUnder(parent);
|
||||
}
|
||||
|
||||
Ultima1Game *Action::getRoot() {
|
||||
return static_cast<Ultima1Game *>(TreeItem::getRoot());
|
||||
}
|
||||
|
||||
Ultima1Map *Action::getMap() {
|
||||
return static_cast<Ultima1Map *>(TreeItem::getMap());
|
||||
}
|
||||
|
||||
GameResources *Action::getRes() {
|
||||
return getRoot()->_res;
|
||||
}
|
||||
|
||||
void Action::addStatusMsg(const Common::String &text) {
|
||||
Shared::CStatusMsg msg(text);
|
||||
msg.execute(getView());
|
||||
}
|
||||
|
||||
} // End of namespace Actions
|
||||
} // End of namespace Ultima1
|
||||
} // End of namespace Ultima
|
||||
|
@ -30,6 +30,7 @@ namespace Ultima1 {
|
||||
|
||||
class Ultima1Game;
|
||||
class Ultima1Map;
|
||||
class GameResources;
|
||||
|
||||
namespace Actions {
|
||||
|
||||
@ -54,6 +55,16 @@ public:
|
||||
* Return the game's map
|
||||
*/
|
||||
Ultima1Map *getMap();
|
||||
|
||||
/**
|
||||
* Gets the data resources for the game
|
||||
*/
|
||||
GameResources *getRes();
|
||||
|
||||
/**
|
||||
* Adds a text string to the status area
|
||||
*/
|
||||
void addStatusMsg(const Common::String &text);
|
||||
};
|
||||
|
||||
} // End of namespace Actions
|
||||
|
@ -21,6 +21,10 @@
|
||||
*/
|
||||
|
||||
#include "ultima/ultima1/actions/move.h"
|
||||
#include "ultima/ultima1/game.h"
|
||||
#include "ultima/ultima1/core/map.h"
|
||||
#include "ultima/ultima1/core/transports.h"
|
||||
#include "ultima/ultima1/core/resources.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima1 {
|
||||
@ -30,7 +34,41 @@ BEGIN_MESSAGE_MAP(Move, Action)
|
||||
ON_MESSAGE(MoveMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
bool Move::MoveMsg(Shared::CMoveMsg &msg) {
|
||||
bool Move::MoveMsg(CMoveMsg &msg) {
|
||||
Ultima1Map *map = getMap();
|
||||
WidgetTransport *transport = map->_currentTransport;
|
||||
|
||||
// Figure out the new position
|
||||
Point delta;
|
||||
switch (msg._direction) {
|
||||
case Shared::DIR_LEFT:
|
||||
delta = Point(-1, 0);
|
||||
break;
|
||||
case Shared::DIR_RIGHT:
|
||||
delta = Point(1, 0);
|
||||
break;
|
||||
case Shared::DIR_UP:
|
||||
delta = Point(0, -1);
|
||||
break;
|
||||
case Shared::DIR_DOWN:
|
||||
delta = Point(0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if the given transport type can move to the new position
|
||||
Point newPos = map->getPosition() + delta;
|
||||
if (transport->canMoveTo(newPos)) {
|
||||
// Shift the viewport
|
||||
map->shiftViewport(delta);
|
||||
|
||||
// Move to the new position
|
||||
if (transport->moveTo(newPos))
|
||||
addStatusMsg(getRes()->DIRECTION_NAMES[msg._direction - 1]);
|
||||
} else {
|
||||
// Nope, so show a blocked message
|
||||
addStatusMsg(getRes()->BLOCKED);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "ultima/ultima1/core/map.h"
|
||||
#include "ultima/ultima1/core/widget_player.h"
|
||||
#include "ultima/ultima1/core/transports.h"
|
||||
#include "ultima/ultima1/game.h"
|
||||
#include "ultima/shared/core/file.h"
|
||||
|
||||
@ -31,7 +31,8 @@ namespace Ultima1 {
|
||||
using Shared::File;
|
||||
|
||||
Ultima1Map::Ultima1Map(Ultima1Game *game) : Shared::Map(), _mapType(MAP_OVERWORLD), _mapStyle(0), _mapIndex(0) {
|
||||
addWidget(new WidgetPlayer(game, this));
|
||||
_currentTransport = new TransportOnFoot(game, this);
|
||||
addWidget(_currentTransport);
|
||||
}
|
||||
|
||||
void Ultima1Map::loadMap(int mapId, uint videoMode) {
|
||||
|
@ -33,6 +33,7 @@ enum MapType {
|
||||
};
|
||||
|
||||
class Ultima1Game;
|
||||
class WidgetTransport;
|
||||
|
||||
class U1MapTile : public Shared::MapTile {
|
||||
public:
|
||||
@ -55,6 +56,7 @@ public:
|
||||
uint _mapStyle; // Map style category for towns & castles
|
||||
uint _mapIndex; // Map index, such as city/castle #; not to be confused with mapId
|
||||
Common::String _name; // Name of map, if applicable
|
||||
WidgetTransport *_currentTransport; // Current means of transport, even if on foot
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -28,6 +28,8 @@ namespace Ultima1 {
|
||||
|
||||
const char *const SRC_STATUS_TEXT[4] = { "Hits:", "Food:", "Exp.:", "Coin:" };
|
||||
|
||||
const char *const SRC_DIRECTION_NAMES[4] = { "West", "East", "North", "South" };
|
||||
|
||||
const char *const SRC_LOCATION_NAMES[85] = {
|
||||
"?",
|
||||
"Britian",
|
||||
@ -119,6 +121,8 @@ const char *const SRC_LOCATION_NAMES[85] = {
|
||||
"The Hole to Hades"
|
||||
};
|
||||
|
||||
const char *const SRC_BLOCKED = "Blocked!";
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
GameResources::GameResources() : LocalResourceFile("ULTIMA1/DATA") {
|
||||
@ -126,12 +130,16 @@ GameResources::GameResources() : LocalResourceFile("ULTIMA1/DATA") {
|
||||
|
||||
GameResources::GameResources(Shared::Resources *resManager) : LocalResourceFile(resManager, "ULTIMA1/DATA") {
|
||||
Common::copy(SRC_STATUS_TEXT, SRC_STATUS_TEXT + 4, STATUS_TEXT);
|
||||
Common::copy(SRC_DIRECTION_NAMES, SRC_DIRECTION_NAMES + 4, DIRECTION_NAMES);
|
||||
Common::copy(SRC_LOCATION_NAMES, SRC_LOCATION_NAMES + 85, LOCATION_NAMES);
|
||||
BLOCKED = SRC_BLOCKED;
|
||||
}
|
||||
|
||||
void GameResources::synchronize() {
|
||||
syncStrings(STATUS_TEXT, 4);
|
||||
syncStrings(DIRECTION_NAMES, 4);
|
||||
syncStrings(LOCATION_NAMES, 32);
|
||||
syncString(BLOCKED);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima1
|
||||
|
@ -36,7 +36,9 @@ protected:
|
||||
virtual void synchronize();
|
||||
public:
|
||||
const char *STATUS_TEXT[4];
|
||||
const char *DIRECTION_NAMES[4];
|
||||
const char *LOCATION_NAMES[85];
|
||||
const char *BLOCKED;
|
||||
public:
|
||||
GameResources();
|
||||
GameResources(Shared::Resources *resManager);
|
||||
|
48
engines/ultima/ultima1/core/transports.cpp
Normal file
48
engines/ultima/ultima1/core/transports.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/ultima1/core/transports.h"
|
||||
#include "ultima/ultima1/core/map.h"
|
||||
#include "common/algorithm.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima1 {
|
||||
|
||||
bool TransportOnFoot::canMoveTo(const Point &destPos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransportOnFoot::moveTo(const Point &destPos) {
|
||||
_map->setPosition(destPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TransportOnFoot::isPrincessSaved() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void TransportOnFoot::princessSaved() {
|
||||
|
||||
}
|
||||
|
||||
} // End of namespace Ultima1
|
||||
} // End of namespace Ultima
|
100
engines/ultima/ultima1/core/transports.h
Normal file
100
engines/ultima/ultima1/core/transports.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA_ULTIMA1_CORE_WIDGET_PLAYER_H
|
||||
#define ULTIMA_ULTIMA1_CORE_WIDGET_PLAYER_H
|
||||
|
||||
#include "ultima/shared/core/map.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima1 {
|
||||
|
||||
class WidgetTransport : public Shared::MapWidget {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
WidgetTransport(Shared::Game *game, Shared::Map *map) : Shared::MapWidget(game, map) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~WidgetTransport() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given transport type can move to a given position on the map
|
||||
* @param destPos Specified new position
|
||||
*/
|
||||
virtual bool canMoveTo(const Point &destPos) = 0;
|
||||
|
||||
/**
|
||||
* Moves to a given position
|
||||
* @param destPos Specified new position
|
||||
* @returns If true, the direction moved will be printed in the status area
|
||||
*/
|
||||
virtual bool moveTo(const Point &destPos) = 0;
|
||||
};
|
||||
|
||||
class TransportOnFoot : public WidgetTransport {
|
||||
private:
|
||||
/**
|
||||
* Checks for whether a princess has been saved from a castle being left
|
||||
*/
|
||||
bool isPrincessSaved() const;
|
||||
|
||||
/**
|
||||
* Called for a princess being saved
|
||||
*/
|
||||
void princessSaved();
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
TransportOnFoot(Shared::Game *game, Shared::Map *map) : WidgetTransport(game, map) {}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~TransportOnFoot() {}
|
||||
|
||||
/**
|
||||
* Get the tile for the transport method
|
||||
*/
|
||||
virtual uint getTileNum() const { return 10; }
|
||||
|
||||
/**
|
||||
* Returns true if the given transport type can move to a given position on the map
|
||||
*/
|
||||
virtual bool canMoveTo(const Point &destPos);
|
||||
|
||||
/**
|
||||
* Moves to a given position
|
||||
* @param destPos Specified new position
|
||||
* @returns If true, the direction moved will be printed in the status area
|
||||
*/
|
||||
virtual bool moveTo(const Point &destPos);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima1
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
@ -63,17 +63,17 @@ void GameView::draw() {
|
||||
}
|
||||
|
||||
bool GameView::VirtualKeyCharMsg(CVirtualKeyCharMsg &msg) {
|
||||
if (msg._keyState.keycode == Common::KEYCODE_UP || msg._keyState.keycode == Common::KEYCODE_KP8) {
|
||||
if (msg._keyState.keycode == Common::KEYCODE_LEFT || msg._keyState.keycode == Common::KEYCODE_KP4) {
|
||||
Shared::CMoveMsg move(Shared::DIR_LEFT);
|
||||
move.execute(this);
|
||||
} else if (msg._keyState.keycode == Common::KEYCODE_RIGHT || msg._keyState.keycode == Common::KEYCODE_KP6) {
|
||||
Shared::CMoveMsg move(Shared::DIR_RIGHT);
|
||||
move.execute(this);
|
||||
} else if (msg._keyState.keycode == Common::KEYCODE_UP || msg._keyState.keycode == Common::KEYCODE_KP8) {
|
||||
Shared::CMoveMsg move(Shared::DIR_UP);
|
||||
move.execute(this);
|
||||
} else if (msg._keyState.keycode == Common::KEYCODE_DOWN || msg._keyState.keycode == Common::KEYCODE_KP2) {
|
||||
Shared::CMoveMsg move(Shared::DIR_LEFT);
|
||||
move.execute(this);
|
||||
} else if (msg._keyState.keycode == Common::KEYCODE_LEFT || msg._keyState.keycode == Common::KEYCODE_KP4) {
|
||||
Shared::CMoveMsg move(Shared::DIR_LEFT);
|
||||
move.execute(this);
|
||||
} else if (msg._keyState.keycode == Common::KEYCODE_RIGHT || msg._keyState.keycode == Common::KEYCODE_KP6) {
|
||||
Shared::CMoveMsg move(Shared::DIR_LEFT);
|
||||
Shared::CMoveMsg move(Shared::DIR_DOWN);
|
||||
move.execute(this);
|
||||
} else {
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user