Map/Thing collision detection more or less works. Lacking in functionality, but checking/blocking works.

master
kts 2015-03-16 04:52:01 -07:00
parent f92517fe55
commit 798e298ca5
10 changed files with 104 additions and 13 deletions

View File

@ -39,7 +39,7 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>..\..\src;..\..\src\render;..\..\src\states;..\..\src\abilities;..\..\src\things;C:\Dev\glew-1.11.0\include;C:\Dev\SDL2-2.0.3\include;$(IncludePath)</IncludePath>
<IncludePath>..\..\src;..\..\src\render;..\..\src\states;..\..\src\abilities;..\..\src\proclib;..\..\src\things;C:\Dev\glew-1.11.0\include;C:\Dev\SDL2-2.0.3\include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Dev\SDL2-2.0.3\lib\x86;C:\Dev\glew-1.11.0\lib\Release\Win32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

View File

@ -1,8 +1,12 @@
#include "QMap.hpp"
#include <stdlib.h>
#include "Log.hpp"
#include <iterator>
#include <cmath>
QMap::QMap(int w, int h) {
north = east = south = west = NULL;
name = "Realm of Non-Being and Void";
setSize(w, h);
}
QMap::QMap(const char *from_file) {
@ -39,7 +43,37 @@ int QMap::setTile(int x, int y, Tile *new_tile) {
//
int QMap::addThing(Thing *thing, int x, int y) {
things.push_back(thing);
thing->setPosition(x*16, y*16);
thing->setPosition(x*32, y*16);
thing->setMap(this);
return things.size();
}
// collision
Thing *QMap::checkThings(Thing *thing, float x, float y, float w, float h) {
Vec3 pos = thing->getPosition();
pos.x += x; pos.y += y;
std::vector<Thing*>::iterator othing_it, othing_end;
for (othing_it = things.begin(), othing_end = things.end(); othing_it != othing_end; ++othing_it) {
Thing *othing = *othing_it;
if (thing == othing) continue;
Sprite *osprite = othing->getSprite();
Vec3 opos = othing->getPosition();
//opos.x += osprite->getWidth()/2; opos.y += osprite->getHeight()/4;
if (pos.x+w >= opos.x-osprite->getWidth()/2 && pos.x-w <= opos.x+osprite->getWidth()/2) {
if (pos.y+h >= opos.y && pos.y-h <= opos.y+osprite->getHeight()/4) {
return othing;
}
}
}
return NULL;
}
Tile *QMap::checkTiles(Thing *thing, float x, float y, float w, float h) {
Vec3 pos = thing->getPosition();
pos.x += x; pos.y += y;
pos.x += w; pos.y += thing->getSprite()->getHeight() + thing->getSprite()->getHeight()/4;
int tx = std::floor(pos.x + 0.5);
int ty = std::floor(pos.y + 0.5);
tx /= 32;
ty /= 32;
if (pos.x < 0 || pos.y < 0 || tx >= width || ty >= height) return NULL;
return tiles[tx][ty];
}

View File

@ -3,6 +3,7 @@
#include "Thing.hpp"
#include "Tile.hpp"
#include <vector>
#include <string>
class QMap {
friend class GameState;
public:
@ -13,7 +14,11 @@ class QMap {
Tile* getTile(int x, int y);
int setTile(int x, int y, Tile *tile);
int addThing(Thing *thing, int x, int y);
Thing *checkThings(Thing *thing, float x, float y, float w, float h);
Tile *checkTiles(Thing *thing, float x, float y, float w, float h);
std::string getName() { return name; };
protected:
std::string name;
QMap *north;
QMap *south;
QMap *east;

View File

@ -3,6 +3,8 @@
Tile::Tile() {
sprite = new Sprite("data/sprites/void_floors.png", 16, 16);
sprite->setOffset(0, 0);
next = NULL;
prev = NULL;
}
Tile::~Tile() {
}

View File

@ -17,6 +17,8 @@ class Tile {
TILE_BLOCKING = (1 << 1)
};
protected:
Tile *prev;
Tile *next;
Sprite *sprite; // how inefficient can we do this?
};
#endif

View File

@ -1,6 +1,7 @@
#include "VampiricNom.hpp"
#include "Controller.hpp"
#include "Thing.hpp"
#include "QMap.hpp"
VampiricNom::VampiricNom() {
name = "Vampiric Noms";
@ -11,7 +12,13 @@ VampiricNom::~VampiricNom() {
delete sprite;
}
int VampiricNom::onUse() {
owner->getController()->recvMessage("*nom*");
Vec3 dir = owner->getDirection();
Thing *othing = owner->getMap()->checkThings(owner, dir.x, dir.y, 24, 24);
if (othing != NULL) {
owner->getController()->recvMessage("You sink your teeth into "+othing->getName());
} else {
owner->getController()->recvMessage("You nip at the air.");
}
return 0;
}
int VampiricNom::onPrompt() {

View File

@ -42,11 +42,11 @@ GameState::GameState() {
outline_program_uv = glGetAttribLocation(outline_program, "uv");
current_map = new QMap(16, 16);
current_map->setTile(4, 4, new Tile());
current_map->setTile(0, 0, new Tile());
current_map->setTile(1, 0, new Tile());
current_map->setTile(2, 1, new Tile());
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
current_map->setTile(x, y, new Tile());
}
}
pc.thing = new GnashingGibber();
pc.thing->setController(&pc);
@ -55,6 +55,8 @@ GameState::GameState() {
current_map->addThing(new Denizen(), 2, 2);
current_map->addThing(new SightSeer(), 4, 4);
ui_state = new UiSubState();
ui_sheet = new Ui("data/sprites/ui_sheet.png", 128, 128);
@ -67,6 +69,9 @@ GameState::GameState() {
ui_sheet_name = new UiText("Gnashing Gibber", core.getFont("data/fonts/default.ttf"), color);
ui_state->pushUi(ui_sheet_name);
ui_map_name = new UiText(current_map->getName().c_str(), core.getFont("data/fonts/default.ttf"), color);
ui_state->pushUi(ui_map_name);
ui_controls = new Ui("data/sprites/ui_controls.png", 192, 128);
for (int i = 0; i < 10; i++) {
@ -113,6 +118,8 @@ int GameState::onEvent(SDL_Event event) {
ui_state->camera->setSize(event.window.data2);
ui_state->camera->updateProjection(event.window.data1, event.window.data2);
ui_state->camera->doRefresh();
camera->setPosition(pc.thing->position.x, camera->getPosition().y, -pc.thing->position.y);
camera->doRefresh();
refreshUi();
refreshConsole();
} else {
@ -149,14 +156,35 @@ int GameState::doProcess(unsigned int ticks) {
thing->getSprite()->doAnimation(ticks);
float x = thing->velocity.x;
float y = thing->velocity.y;
if (x != 0) thing->velocity.x += -x/4;
if (y != 0) thing->velocity.y += -y/4;
if (x != 0) thing->velocity.x += -x/2;
if (y != 0) thing->velocity.y += -y/2;
if (thing->velocity.x > -0.05 && thing->velocity.x < 0.05) thing->velocity.x = 0;
if (thing->velocity.y > -0.05 && thing->velocity.y < 0.05) thing->velocity.y = 0;
if (x != 0 || y != 0) {
thing->position.x += x;
thing->position.y += y;
thing->getSprite()->setPosition(thing->position.x, thing->position.y);
Thing *othing = current_map->checkThings(thing, x, y, thing->getSprite()->getWidth(), thing->getSprite()->getHeight()/3);
if (othing != NULL) {
thing->setVelocity(Vec3(0, 0, 0));
thing->doTouch(othing);
othing->onTouch(thing);
}
Tile *tile = current_map->checkTiles(thing, x, y, thing->getSprite()->getWidth(), thing->getSprite()->getHeight()/3);
if (tile == NULL) {
thing->setVelocity(Vec3(0, 0, 0));
continue;
} else {
Tile *next_tile = tile;
int do_break = 0;
do {
if (next_tile->onTouch(thing) == Tile::TILE_BLOCKING) {
thing->setVelocity(Vec3(0, 0, 0));
do_break = 1;
}
} while((next_tile = tile->next) != NULL);
if (do_break) continue;
}
if (othing == NULL) {
thing->setPosition(thing->position.x+x, thing->position.y+y);
}
}
}
// 4. Finally, set the camera to the player's current thing
@ -282,6 +310,9 @@ int GameState::refreshUi() {
ui_sheet->setPosition(width - ui_sheet->getWidth()*2, 0);
ui_sheet->doRefresh(width, height);
ui_map_name->setPosition(ui_sheet->x + 8, ui_sheet->y+6);
ui_map_name->doRefresh(width, height);
ui_character->setPosition(ui_sheet->x + 44 - (ui_character->getWidth()), ui_sheet->y+ 110 - (ui_character->getHeight()));
ui_character->doRefresh(width, height);

View File

@ -50,6 +50,7 @@ class GameState : public State {
Ui *ui_sheet;
Ui *ui_character;
UiText *ui_sheet_name;
UiText *ui_map_name;
Ui *ui_controls;
UiText *ui_console;
UiText *ui_intro;

View File

@ -31,6 +31,10 @@ int Thing::doThink(unsigned int ticks) {
}
return 0;
}
int Thing::doTouch(Thing *touched) {
if (controller != NULL) controller->recvMessage("You hit "+touched->name);
return 0;
}
int Thing::onTouch(Thing *toucher) {
return 0;
}

View File

@ -20,6 +20,7 @@ class Thing {
~Thing();
// interface
int doThink(unsigned int ticks);
virtual int doTouch(Thing *touched);
virtual int onTouch(Thing *thing);
virtual int onThought(Thought thought);
//
@ -32,8 +33,10 @@ class Thing {
void setController(Controller *controller_) { controller = controller_; };
Controller* getController() { return controller; };
void printMsg(std::string string);
std::string getName() { return name; };
//
void setMap(QMap *qmap) { map = qmap; };
QMap *getMap() { return map; };
//
enum Flags {
THING_DESTROY = (1 << 1)
@ -44,6 +47,8 @@ class Thing {
void setVelocity(Vec3 vel);
void setPosition(Vec3 pos);
void setPosition(float x, float y);
Vec3 getPosition() { return position; };
Vec3 getDirection() { return direction; };
// getters for internal stuff
Sprite *getSprite() { return sprite; };
// oh boy oh boy, our stats!