Added AiController - no real substance yet. UI shaders may now have a vertical 'fade' (darkening, ultimately). UI shader should have outlining be toggle-able via a boolean or similar (or perhaps separate shaders for text). GodHand now succesfully swaps entities when used. UI elements may be rotated now. Added a silly Ui Time element that simply rotates each tick. Added remove and check for Thing abilities. Need to flesh out needed Thing logic more. Also need to update Ui character sheet based on GodHand swap.

master
kts 2015-03-23 04:21:36 -07:00
parent 798e298ca5
commit 191814cb7f
21 changed files with 197 additions and 46 deletions

View File

@ -18,7 +18,7 @@ OBJ=main.o fio.o Core.o Log.o QMap.o Tile.o Thought.o
OBJ+=render/Quat.o render/Mat4.o render/Vec.o render/Mesh.o render/Texture.o render/Program.o render/RenderScene.o render/RenderSet.o render/RenderObject.o render/RenderCamera.o render/RenderView.o render/Sprite.o
OBJ+=render/Font.o render/Ui.o render/UiText.o
OBJ+=states/GameState.o states/UiSubState.o
OBJ+=Controller.o PlayerController.o
OBJ+=Controller.o PlayerController.o AiController.o
OBJ+=things/Thing.o things/Denizen.o things/SightSeer.o things/GnashingGibber.o
OBJ+=abilities/Ability.o abilities/GodHand.o abilities/VampiricNom.o
OBJ_DIR=obj

View File

@ -14,4 +14,4 @@ void main() {
gl_FragColor = vec4(0.75, 0.5, 0.5, c);
if (gl_FragColor.a == 0.0) discard;
//gl_FragColor = vec4(0.5, 0.0, 0.0, 0.5);
}
}

View File

@ -2,13 +2,34 @@
// uniforms
uniform sampler2D texture_sampler;
uniform float transparency;
uniform float vertical_fade;
// input
varying vec2 frag_uv;
void main() {
gl_FragColor = texture2D(texture_sampler, frag_uv);
gl_FragColor.a -= transparency;
gl_FragColor.a -= 0.10;
// grossly outline the UI element
if (gl_FragColor.a < 0.1 && frag_uv.x >= 0.001 && frag_uv.x <= 0.999 && frag_uv.y >= 0.001 && frag_uv.y <= 0.999) {
vec4 t = texture2D(texture_sampler, frag_uv + vec2( 0.0f, -0.0025f ));
vec4 b = texture2D(texture_sampler, frag_uv + vec2( 0.0f, 0.0025f ));
vec4 l = texture2D(texture_sampler, frag_uv + vec2( -0.0025f, 0.0f ));
float c = 0.0f;
if (t.a > 0.75) {
gl_FragColor = vec4(0.5 - t.r, 0.5 - t.g, 0.5 - t.b, 1.0 - transparency);
} else if (b.a > 0.75) {
gl_FragColor = vec4(0.5 - b.r, 0.5 - b.g, 0.5 - b.b, 1.0 - transparency);
} else if (l.a > 0.75) {
gl_FragColor = vec4(0.5 - l.r, 0.5 - l.g, 0.5 - l.b, 1.0 - transparency);
}
} else {
gl_FragColor.a -= transparency;
gl_FragColor.a -= 0.10;
}
// modify alpha/color based on UV offsets.
if (vertical_fade > 0) {
//gl_FragColor.a -= 0.35 - frag_uv.y; // this increases alpha towards top
gl_FragColor.rgb -= (0.35 - frag_uv.y/2); // this darkens rgb towards top
}
if (gl_FragColor.a == 0.0) discard;
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

View File

@ -0,0 +1,22 @@
#include "AiController.hpp"
#include "Thought.hpp"
#include "Thing.hpp"
#include "Core.hpp"
#include "Log.hpp"
AiController::AiController() {
}
AiController::~AiController() {
}
void AiController::doThink(int ticks) {
std::vector<Thing*>::iterator t_it, t_end;
for (t_it = things.begin(), t_end = things.end(); t_it != t_end; ++t_it) {
Thing *thing = *t_it;
}
}
void AiController::controlThing(Thing *thing_) {
things.push_back(thing_);
}
void AiController::recvMessage(std::string string) {
LOG(LOG_INFO) << string;
}

View File

@ -0,0 +1,16 @@
#ifndef AICONTROLLER_HPP
#define AICONTROLLER_HPP
#include "Controller.hpp"
#include <vector>
class AiController : Controller {
friend class GameState;
public:
AiController();
~AiController();
virtual void doThink(int ticks);
virtual void controlThing(Thing *thing_);
virtual void recvMessage(std::string string);
protected:
std::vector<Thing*> things;
};
#endif

View File

@ -3,7 +3,7 @@
Controller::Controller() {
thing = NULL;
tick_rate = 50;
}
Controller::~Controller() {
}

View File

@ -14,7 +14,10 @@ class Controller {
Controller();
~Controller();
virtual void recvMessage(std::string string) { return; };
virtual void doThink(int ticks) { return; };
virtual void controlThing(Thing *thing_) { thing = thing_; };
protected:
Thing *thing;
int tick_rate;
};
#endif

View File

@ -47,9 +47,22 @@ int Core::initSystem() {
LOG(LOG_ERROR) << TTF_GetError();
return 1;
}
// get our displayyyy
// ** Get our display, checking bounding boxes for multi monitor setups
int di = SDL_GetNumVideoDisplays()-1; // display index (monitor)
/*int mx, my;
SDL_GetGlobalMouseState(&mx, &my); // SDL 2.0.4
LOG(LOG_INFO) << "mouse: " << mx << "x" << my;
int dc = SDL_GetNumVideoDisplays();
for (di = 0; di < dc; di++) {
SDL_Rect dr;
SDL_GetDisplayBounds(di, &dr);
if ((mx >= dr.x && mx <= dr.x+dr.w) && (my >= dr.y && my <= dr.y+dr.h)) {
break;
}
}*/
// get our window size from display
SDL_DisplayMode dmode;
SDL_GetDesktopDisplayMode(0, &dmode);
SDL_GetCurrentDisplayMode(di, &dmode);
v_width = dmode.w - dmode.w/4; // TEMP: just for a smaller window per-default
v_height = dmode.h - dmode.h/4;
v_flags = SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE;
@ -279,8 +292,8 @@ Font* Core::getFont(const char *font_name) {
char *fbuf = NULL;
size_t flen = 0;
flen = fileToMem(font_name, &fbuf);
font = new Font(font_name, 13, fbuf, flen);
font = new Font(font_name, 11, fbuf, flen);
font_table->set(font_name, font);
}
return font;
}
}

View File

@ -1,4 +1,5 @@
#include "GodHand.hpp"
#include "QMap.hpp"
#include "Controller.hpp"
#include "Thing.hpp"
@ -11,10 +12,22 @@ GodHand::~GodHand() {
delete sprite;
}
int GodHand::onUse() {
owner->getController()->recvMessage("The nature of Things have changed.");
Vec3 dir = owner->getDirection();
Thing *othing = owner->getMap()->checkThings(owner, dir.x, dir.y, 24, 24);
if (othing != NULL) {
Controller *ocontroller = othing->getController();
othing->setController(owner->getController());
owner->setController(ocontroller);
owner->remAbility(name);
othing->unshiftAbility(this);
owner->getController()->recvMessage("The nature of Things have changed.");
// TODO: haiku-based swap difference, each ability has 5 and 7 syllable versions that create a 5-7-5 message
} else {
owner->getController()->recvMessage("You yearn for a new host.");
}
return 0;
}
int GodHand::onPrompt() {
owner->getController()->recvMessage("Soul swap with what?");
return 0;
}
}

View File

@ -64,7 +64,6 @@ void Sprite::doAnimation(unsigned int ticks) {
}
//
void Sprite::setOffset(int col_, int row_) {
LOG(LOG_INFO) << x << "x" << y;
col = col_;
row = row_;
uv_x = col * uvw;
@ -76,4 +75,4 @@ void Sprite::setPosition(float xpos, float ypos) {
// NOTE: since we're using orthogonal rendering, we send ypos as the depth as well (so we don't have to sort)
object->setTranslation(xpos, ypos, -ypos);
object->calcMatrix();
}
}

View File

@ -10,6 +10,7 @@ Ui::Ui() {
timeout = 0;
timeout_elapsed = 0;
transparency = 0.0f;
vertical_fade = 0.0f;
}
Ui::Ui(const char *filename, int width_, int height_) {
texture = NULL;
@ -19,6 +20,7 @@ Ui::Ui(const char *filename, int width_, int height_) {
timeout = 0;
timeout_elapsed = 0;
transparency = 0.0f;
vertical_fade = 0.0f;
setImage(filename, width_, height_);
}
Ui::~Ui() {
@ -71,6 +73,11 @@ void Ui::setPosition(float xpos, float ypos) {
x = xpos;
y = ypos;
}
void Ui::setRotation(int angle_) {
angle = angle_;
object->setRotation(0, angle, 0);
object->calcMatrix();
}
void Ui::setOffset(int col_, int row_) {
col = col_;
row = row_;

View File

@ -15,12 +15,14 @@ class Ui {
virtual void setPosition(float x, float y);
void setOffset(int col, int row);
void setTimeout(int time);
void setRotation(int angle);
Texture *getTexture() { return texture; };
RenderObject *getObject() { return object; };
int getWidth() { return width; };
int getHeight() { return height; };
void doRefresh(float screen_w, float screen_h);
void doProcess(unsigned int ticks);
int getAngle() { return angle; };
int flags;
enum Flags {
UI_DESTROY = (1 << 1)
@ -32,12 +34,14 @@ class Ui {
int width, height; // width and height of ui element
int col, row; // column and row in spritesheet
float x, y; // x and y in coordinates
int angle; // angle in eular
int max_x, max_y; // max x and y coordinates derived from texture
float uv_x, uv_y; // uv x and y offsets
float uvw, uvh; // sprite size in UV terms
float timeout; // time to keep this Ui up before closing it
float timeout_elapsed; // elapsed time for ^
float transparency; // alpha of this element, 1.0 = full transparent, 0.0 = full opacity
float vertical_fade; // vertical fading to apply, 0 = none
};
bool destroyUi(Ui* ui);

View File

@ -4,12 +4,14 @@
#include <sstream>
UiText::UiText() {
vertical_fade = 1.0f;
}
UiText::UiText(const char *text_, Font *font_, SDL_Color color_) {
text = text_;
font = font_;
color = color_;
texture = NULL;
vertical_fade = 1.0f;
setText(text_);
}
UiText::~UiText() {
@ -30,11 +32,15 @@ void UiText::setText(std::string text_) {
text = text_;
buildText(text);
width = texture->w/2; height = texture->h/2;
x = y = 0;
row = col = 0;
width = texture->w/2; height = texture->h/2;
max_x = texture->w/2 / width;
max_y = texture->h/2 / height;
/*width = texture->w; height = texture->h;
max_x = texture->w / width;
max_y = texture->h / height;*/
object = new RenderObject();
object->setScale(1.0f, 1.0f, 1.0f);
object->calcMatrix();
@ -73,9 +79,7 @@ Texture *UiText::buildText(std::string string) {
int width = 0;
int height = 0;
SDL_Surface *line_surface = NULL;
LOG(LOG_INFO) << "about to build!";
while(std::getline(ss, line, '\n')) {
//LOG(LOG_INFO) << line;
line_surface = TTF_RenderUTF8_Blended(font->font, line.c_str(), color);
if (line_surface == NULL) {
line_surfaces.push_back(NULL);
@ -86,7 +90,6 @@ Texture *UiText::buildText(std::string string) {
height += line_surface->h;
}
}
LOG(LOG_INFO) << "built!";
SDL_Surface *final_surface = SDL_CreateRGBSurface(0, width, height, line_surface->format->BitsPerPixel, line_surface->format->Rmask, line_surface->format->Gmask, line_surface->format->Bmask, line_surface->format->Amask);
SDL_Rect offset = { 0, 0, 0, 0 };
std::vector<SDL_Surface*>::iterator surface_it, surface_end;
@ -105,4 +108,4 @@ Texture *UiText::buildText(std::string string) {
texture->buildTexture();
//SDL_FreeSurface(final_surface); // NOTE: surface is freed by the Texture
return texture;
}
}

View File

@ -13,9 +13,10 @@
GameState::GameState() {
camera = new RenderCamera();
camera->setRenderView(new RenderView(core.getWidth(), core.getHeight()));
camera->setPitch(90.0f);
//camera->setPitch(75.0f);
//camera->setPosition(0, 1000, 0);
/*camera->setPosition(0, core.getHeight()*2, 0);*/
camera->setPosition(0, 0, 0);
camera->setPitch(90.0f);
camera->setRenderMode(1);
camera->setSize(core.getHeight());
camera->updateProjection(core.getWidth(), core.getHeight());
@ -48,14 +49,20 @@ GameState::GameState() {
}
}
pc.thing = new GnashingGibber();
pc.thing->setController(&pc);
pc.thing->unshiftAbility(new GodHand());
current_map->addThing(pc.thing, 1, 1);
Thing *thing = new GnashingGibber();
thing->setController(&pc);
thing->unshiftAbility(new GodHand());
current_map->addThing(thing, 1, 1);
current_map->addThing(new Denizen(), 2, 2);
thing = new Denizen();
thing->setController(&ac);
current_map->addThing(new SightSeer(), 4, 4);
current_map->addThing(thing, 2, 2);
thing = new SightSeer();
thing->setController(&ac);
current_map->addThing(thing, 4, 4);
ui_state = new UiSubState();
@ -65,6 +72,10 @@ GameState::GameState() {
ui_state->pushUi(ui_character);
ui_character->setImage("data/sprites/gnashing_gibber.png", 16, 32);
ui_time = new Ui("data/sprites/ui_time.png", 16, 16);
ui_time->setPosition(32, 32);
ui_state->pushUi(ui_time);
SDL_Color color = { 128, 255, 128, 255 };
ui_sheet_name = new UiText("Gnashing Gibber", core.getFont("data/fonts/default.ttf"), color);
ui_state->pushUi(ui_sheet_name);
@ -139,8 +150,14 @@ int GameState::onEvent(SDL_Event event) {
int GameState::doProcess(unsigned int ticks) {
ui_state->doProcess(ticks);
// 1. for each AiController, run their doThink
std::vector<Controller*>::iterator c_it, c_end;
for (c_it = controllers.begin(), c_end = controllers.end(); c_it != c_end; ++c_it) {
Controller *controller = *c_it;
controller->doThink(ticks);
}
// 2. for each thing, run their doThink
if ((pc.thing->thoughts.size() <= 0 && pc.thing->thought_current.type == 0) && pc.thing->velocity.x == 0 && pc.thing->velocity.y == 0) return 0;
ui_time->setRotation(ui_time->getAngle()+1);
std::vector<Thing*>::iterator thing_it, thing_end;
for (thing_it = current_map->things.begin(), thing_end = current_map->things.end(); thing_it != thing_end; ++thing_it) {
Thing *thing = *thing_it;
@ -156,8 +173,8 @@ 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/2;
if (y != 0) thing->velocity.y += -y/2;
if (x != 0) thing->velocity.x += -x/4;
if (y != 0) thing->velocity.y += -y/4;
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) {
@ -165,7 +182,6 @@ int GameState::doProcess(unsigned int ticks) {
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) {
@ -189,6 +205,7 @@ int GameState::doProcess(unsigned int ticks) {
}
// 4. Finally, set the camera to the player's current thing
camera->setPosition(pc.thing->position.x, camera->getPosition().y, -pc.thing->position.y);
//camera->setPosition(pc.thing->position.x, camera->getPosition().y, -pc.thing->position.y*1.5);
camera->doRefresh();
return 0;
}
@ -306,6 +323,9 @@ int GameState::doRender() {
int GameState::refreshUi() {
int width = core.getWidth();
int height = core.getHeight();
ui_time->setPosition(16, 16);
ui_time->doRefresh(width, height);
ui_sheet->setPosition(width - ui_sheet->getWidth()*2, 0);
ui_sheet->doRefresh(width, height);

View File

@ -2,6 +2,7 @@
#define GAMESTATE_HPP
#include "State.hpp"
#include "Controller.hpp"
#include "AiController.hpp"
#include "PlayerController.hpp"
#include "QMap.hpp"
#include "Ui.hpp"
@ -23,6 +24,7 @@ class GameState : public State {
std::vector<QMap*> maps;
std::vector<Controller*> controllers;
PlayerController pc;
AiController ac;
// rendering
GLuint program;
// get our uniforms (move elsewhere)
@ -52,6 +54,7 @@ class GameState : public State {
UiText *ui_sheet_name;
UiText *ui_map_name;
Ui *ui_controls;
Ui *ui_time;
UiText *ui_console;
UiText *ui_intro;
std::vector<Ui*> ui_abilities;

View File

@ -2,6 +2,7 @@
#include "Core.hpp"
#include <algorithm> // remove_if
#include <iterator>
#include "Log.hpp"
UiSubState::UiSubState() {
// UI camera
@ -21,6 +22,7 @@ UiSubState::UiSubState() {
ui_program_texture = glGetUniformLocation(ui_program, "texture_sampler");
ui_program_uv_offset = glGetUniformLocation(ui_program, "uv_offset");
ui_program_transparency = glGetUniformLocation(ui_program, "transparency");
ui_program_v_fade = glGetUniformLocation(ui_program, "vertical_fade"); // FIXME: should this be a bool?
// get our attributes
ui_program_vp = glGetAttribLocation(ui_program, "vp");
ui_program_uv = glGetAttribLocation(ui_program, "uv");
@ -74,8 +76,11 @@ int UiSubState::doRender() {
glUniform2f(ui_program_uv_offset, 0.0f, 0.0f);
// send alpha
glUniform1f(ui_program_transparency, ui->transparency);
// send fade amount
glUniform1f(ui_program_v_fade, ui->vertical_fade);
LOG(LOG_INFO) << "vfade is " << ui->vertical_fade;
// draw
glDrawArrays(GL_TRIANGLES, 0, mesh->vertices.size());
}
return 0;
}
}

View File

@ -24,6 +24,7 @@ class UiSubState {
GLuint ui_program_modelview;
GLuint ui_program_texture;
GLuint ui_program_transparency;
GLuint ui_program_v_fade;
// get our attributes
GLuint ui_program_vp;
GLuint ui_program_uv;

View File

@ -53,6 +53,8 @@ int GnashingGibber::onThought(Thought thought) {
}
return 0;
}
int GnashingGibber::onTouch(Thing *thing) {
int GnashingGibber::onTouch(Thing *touched) {
controller->recvMessage("You bite "+touched->getName());
touched->getController()->recvMessage(name+" bites you");
return 0;
}

View File

@ -32,13 +32,8 @@ 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;
}
int Thing::onThought(Thought thought) {
onTouch(touched);
touched->onTouched(this);
return 0;
}
/* ======== Adding/Access ======== */
@ -68,6 +63,25 @@ Ability *Thing::getAbility(int number) {
}
return abilities.at(number);
}
Ability* Thing::remAbility(std::string ability_name) {
std::deque<Ability*>::iterator abil_it, abil_end;
for (abil_it = abilities.begin(), abil_end = abilities.end(); abil_it != abil_end; ++abil_it) {
Ability *abil = *abil_it;
if (abil->getName() == ability_name) {
abilities.erase(abil_it);
return abil;
}
}
return NULL;
}
int Thing::hasAbility(std::string ability_name) {
std::deque<Ability*>::iterator abil_it, abil_end;
for (abil_it = abilities.begin(), abil_end = abilities.end(); abil_it != abil_end; ++abil_it) {
Ability *abil = *abil_it;
if (abil->getName() == ability_name) return 1;
}
return 0;
}
/* ======== Velocity/Position ======== */
void Thing::addVelocity(Vec3 vel) {
velocity += vel;

View File

@ -20,17 +20,20 @@ class Thing {
~Thing();
// interface
int doThink(unsigned int ticks);
virtual int doTouch(Thing *touched);
virtual int onTouch(Thing *thing);
virtual int onThought(Thought thought);
int doTouch(Thing *touched);
virtual int onTouch(Thing *touched) { return 0; };
virtual int onTouched(Thing *toucher) { return 0; };
virtual int onThought(Thought thought) { return 0; };
//
int pushThought(Thought thought);
//
Ability *getAbility(int number);
int pushAbility(Ability *ability);
int unshiftAbility(Ability *ability);
int hasAbility(std::string ability);
Ability* remAbility(std::string ability_name);
//
void setController(Controller *controller_) { controller = controller_; };
void setController(Controller *controller_) { controller_->controlThing(this); controller = controller_; };
Controller* getController() { return controller; };
void printMsg(std::string string);
std::string getName() { return name; };
@ -52,9 +55,11 @@ class Thing {
// getters for internal stuff
Sprite *getSprite() { return sprite; };
// oh boy oh boy, our stats!
int speed;
int health;
int damage;
int health; // total health
int armor; // armor, reduces incoming damage
int speed; // movement speed
int damage; // physical damage
int power; // magical power
protected:
QMap *map; // the map to which we belong (this is bad)
Controller *controller;