aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp26
-rw-r--r--src/ui.cpp163
-rw-r--r--src/world.cpp85
3 files changed, 182 insertions, 92 deletions
diff --git a/src/main.cpp b/src/main.cpp
index a5bee95..327bd66 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -140,9 +140,21 @@ void render(){
**** RENDER STUFF HERE ****
**************************/
- currentWorld->draw(&player->loc);
- player->draw();
- ui::putString(0,0,"Hello");
+ currentWorld->draw(&player->loc); // Draw the world around the player
+ player->draw(); // Draw the player
+
+ if(ui::debug){
+ static unsigned int debugDiv=0;
+ static int fps,d;
+ if(++debugDiv==20){
+ fps=1000/deltaTime;
+ d=deltaTime;
+ debugDiv=0;
+ }
+ ui::putText(player->loc.x-SCREEN_WIDTH/2,SCREEN_HEIGHT-ui::fontSize,"FPS: %d\nD: %d\nRes: %ux%u",fps,d,SCREEN_WIDTH,SCREEN_HEIGHT);
+ }
+
+ ui::draw(); // Draw any UI elements if they need to be
for(int i=0;i<=entity.size();i++){
entity[i]->draw();
@@ -160,12 +172,10 @@ void render(){
void logic(){
ui::handleEvents();
- currentWorld->detect(&player->loc,&player->vel,player->width);
+ currentWorld->detect(player);
for(int i=0;i<=entity.size();i++){
- currentWorld->detect(&entity[i]->loc,&entity[i]->vel,entity[i]->width);
- if(entity[i]->alive==true&&entity[i]->type == 1){
+ if(entity[i]->alive&&entity[i]->type == 1){
entity[i]->wander(90, &entity[i]->vel);
}
}
-
-}
+}
diff --git a/src/ui.cpp b/src/ui.cpp
index a2fe7bf..5cfc492 100644
--- a/src/ui.cpp
+++ b/src/ui.cpp
@@ -1,24 +1,32 @@
#include <ui.h>
-#include <world.h>
-#include <ft2build.h>
+#include <world.h> // World-switching stuff
+#include <ft2build.h> // FreeType stuff
#include FT_FREETYPE_H
-#define SDL_KEY e.key.keysym.sym
+#define SDL_KEY e.key.keysym.sym // Keeps the code neater :)
-extern Player *player;
-extern World *currentWorld;
+extern Player *player; // 'player' should be (must be) defined in main.cpp
+extern World *currentWorld; // should/must also be defined in main.cpp
-static FT_Library ftl;
+static FT_Library ftl; // Variables for the FreeType library and stuff
static FT_Face ftf;
static GLuint ftex;
-static unsigned int fontSize;
+
+static bool dialogBoxExists=false;
+static const char *dialogBoxText=NULL;
namespace ui {
+ bool debug=false;
+ unsigned int fontSize;
+ /*
+ * initFonts(), setFontFace(), and setFontSize() are pretty self-explanatory
+ */
void initFonts(void){
if(FT_Init_FreeType(&ftl)){
std::cout<<"Error! Couldn't initialize freetype."<<std::endl;
abort();
}
+ fontSize=12; // to be safe
}
void setFontFace(const char *ttf){
if(FT_New_Face(ftl,ttf,0,&ftf)){
@@ -30,51 +38,75 @@ namespace ui {
fontSize=size;
FT_Set_Pixel_Sizes(ftf,0,fontSize);
}
+ float putChar(float x,float y,char c){
+ unsigned int j;
+ char *buf;
+ float w,h;
+ // Load the first/next character (if possible)
+ if(FT_Load_Char(ftf,c,FT_LOAD_RENDER)){
+ std::cout<<"Error! Unsupported character "<<c<<" ("<<(int)c<<")."<<std::endl;
+ abort();
+ }
+ // Load the bitmap with OpenGL
+ glActiveTexture(GL_TEXTURE0);
+ glGenTextures(1,&ftex);
+ glBindTexture(GL_TEXTURE_2D,ftex);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+ /*
+ * ftf->glyph->bitmap.buffer simply stores a bitmap of the character,
+ * and if OpenGL tries to load it directly it'll mistake it as a simple
+ * red on black texture. Here we allocate enough space to convert this
+ * bitmap to an RGBA-type buffer, also making the text white on black.
+ *
+ * TODO: allow different colors
+ */
+ buf=(char *)malloc(ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows*4);
+ for(j=0;j<ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows;j++){
+ buf[j*4]=255;
+ buf[j*4+1]=255;
+ buf[j*4+2]=255;
+ buf[j*4+3]=ftf->glyph->bitmap.buffer[j]?255:0;
+ }
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,ftf->glyph->bitmap.width,ftf->glyph->bitmap.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
+ // Draw the texture and move the cursor
+ w=ftf->glyph->bitmap.width;
+ h=ftf->glyph->bitmap.rows;
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D,ftex);
+ glBegin(GL_QUADS);
+ glColor3ub(255,255,255);
+ glTexCoord2f(0,1);glVertex2f(x,y);
+ glTexCoord2f(1,1);glVertex2f(x+w,y);
+ glTexCoord2f(1,0);glVertex2f(x+w,y+h);
+ glTexCoord2f(0,0);glVertex2f(x,y+h);
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+ // Free the RGBA buffer and the OpenGL texture
+ free(buf);
+ glDeleteTextures(1,&ftex);
+ return w;
+ }
void putString(const float x,const float y,const char *s){
unsigned int i=0,j;
- float xo=x,yo=y,w,h;
- char *buf;
+ float xo=x,yo=y;
do{
- if(FT_Load_Char(ftf,s[i],FT_LOAD_RENDER)){
- std::cout<<"Error! Unsupported character "<<s[i]<<" ("<<(int)s[i]<<")."<<std::endl;
- return;
- }
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1,&ftex);
- glBindTexture(GL_TEXTURE_2D,ftex);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
- glPixelStorei(GL_UNPACK_ALIGNMENT,1);
- buf=(char *)malloc(ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows*4);
- for(j=0;j<ftf->glyph->bitmap.width*ftf->glyph->bitmap.rows;j++){
- buf[j*4]=255;
- buf[j*4+1]=255;
- buf[j*4+2]=255;
- buf[j*4+3]=ftf->glyph->bitmap.buffer[j]?255:0;
+ if(s[i]=='\n'){
+ yo-=fontSize*1.15;
+ xo=x;
+ }else if(s[i]==' '){
+ xo+=fontSize/2;
+ }else{
+ xo+=putChar(xo,yo,s[i])+fontSize*.1;
}
- glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,ftf->glyph->bitmap.width,ftf->glyph->bitmap.rows,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
- w=ftf->glyph->bitmap.width;
- h=ftf->glyph->bitmap.rows;
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D,ftex);
- glBegin(GL_QUADS);
- glColor3ub(255,255,255);
- glTexCoord2f(0,1);glVertex2f(xo,yo);
- glTexCoord2f(1,1);glVertex2f(xo+w,yo);
- glTexCoord2f(1,0);glVertex2f(xo+w,yo+h);
- glTexCoord2f(0,0);glVertex2f(xo,yo+h);
- glEnd();
- glDisable(GL_TEXTURE_2D);
- xo+=w;
- free(buf);
- glDeleteTextures(1,&ftex);
}while(s[i++]);
}
- void putText(const float x,const float y,const char *str,...){
- va_list args;
- char *buf;
+ void putText(const float x,const float y,const char *str,...){ // putText() simply runs 'str' and the extra arguments though
+ va_list args; // vsnprintf(), which'll store the complete string to a buffer
+ char *buf; // that's then passed to putString()
buf=(char *)calloc(128,sizeof(char));
va_start(args,str);
vsnprintf(buf,128,str,args);
@@ -82,6 +114,17 @@ namespace ui {
putString(x,y,buf);
free(buf);
}
+ void dialogBox(const char *text){
+ dialogBoxExists=true;
+ dialogBoxText=text;
+ }
+ void draw(void){
+ if(dialogBoxExists){
+ glColor3ub(0,0,0);
+ glRectf(player->loc.x-SCREEN_WIDTH/2,SCREEN_HEIGHT,player->loc.x+SCREEN_WIDTH/2,SCREEN_HEIGHT-SCREEN_HEIGHT/4);
+ putString(player->loc.x-SCREEN_WIDTH/2,SCREEN_HEIGHT-fontSize,dialogBoxText);
+ }
+ }
void handleEvents(void){
SDL_Event e;
while(SDL_PollEvent(&e)){
@@ -90,21 +133,31 @@ namespace ui {
gameRunning=false;
break;
case SDL_KEYDOWN:
- if(SDL_KEY==SDLK_ESCAPE)gameRunning=false;
- if(SDL_KEY==SDLK_a){
+ if(SDL_KEY==SDLK_ESCAPE)gameRunning=false; // Exit the game with ESC
+ if(SDL_KEY==SDLK_a){ // Move left
player->vel.x=-.15;
- currentWorld=currentWorld->goWorldLeft(&player->loc,player->width);
+ currentWorld=currentWorld->goWorldLeft(player);
}
- if(SDL_KEY==SDLK_d){
+ if(SDL_KEY==SDLK_d){ // Move right
player->vel.x=.15;
- currentWorld=currentWorld->goWorldRight(&player->loc,player->width);
+ currentWorld=currentWorld->goWorldRight(player);
+ }
+ if(SDL_KEY==SDLK_SPACE)player->vel.y=.25; // Jump
+ if(SDL_KEY==SDLK_i)currentWorld=currentWorld->goWorldBack(player); // Go back a layer if possible
+ if(SDL_KEY==SDLK_k)currentWorld=currentWorld->goWorldFront(player); // Go forward a layer if possible
+ if(SDL_KEY==SDLK_F3)debug^=true;
+
+ // TEMPORARY UNTIL MOUSE
+ if(SDL_KEY==SDLK_t){
+ if(dialogBoxExists){
+ dialogBoxExists=false;
+ dialogBoxText=NULL;
+ }else dialogBox("Hello");
}
- if(SDL_KEY==SDLK_SPACE)player->vel.y=.25;
- if(SDL_KEY==SDLK_i)currentWorld=currentWorld->goWorldBack(&player->loc,player->width);
- if(SDL_KEY==SDLK_k)currentWorld=currentWorld->goWorldFront(&player->loc,player->width);
+
break;
case SDL_KEYUP:
- if(SDL_KEY==SDLK_a)player->vel.x=0;
+ if(SDL_KEY==SDLK_a)player->vel.x=0; // Stop the player if movement keys are released
if(SDL_KEY==SDLK_d)player->vel.x=0;
break;
default:
diff --git a/src/world.cpp b/src/world.cpp
index 891c8cd..b279f2f 100644
--- a/src/world.cpp
+++ b/src/world.cpp
@@ -12,6 +12,8 @@
#define DRAW_Y_OFFSET 50 // Defines how many pixels each layer should be offset from each other on the y axis when drawn.
#define DRAW_SHADE 40 // Defines a shade increment for draw()
+extern std::vector<Entity *>entity;
+
void safeSetColor(int r,int g,int b){ // safeSetColor() is an alternative to directly using glColor3ub() to set
if(r>255)r=255; // the color for OpenGL drawing. safeSetColor() checks for values that are
if(g>255)g=255; // outside the range of an unsigned character and sets them to a safer value.
@@ -24,7 +26,7 @@ void safeSetColor(int r,int g,int b){ // safeSetColor() is an alternative to dir
World::World(unsigned int width){ // Generates the world and sets all variables contained in the World class.
unsigned int i; // Used for 'for' loops
- float inc; // See line 37
+ float inc; // See line 40
lineCount=width+GEN_INC; // Sets line count to the desired width plus GEN_INC to remove incorrect line calculations.
line=(struct line_t *)calloc(lineCount,sizeof(struct line_t)); // Allocate memory for the array 'line'
@@ -46,12 +48,15 @@ World::World(unsigned int width){ // Generates the world and sets all variables
// in the form (where n represents the color) glColor3ub(n,n-50,n-100)
}
x_start=0-getWidth(this)/2+GEN_INC/2*HLINE; // Calculate x_start (explained in world.h)
- behind=infront=NULL; // Set pointers to other worlds to NULL
- toLeft=toRight=NULL; // to avoid accidental calls to goWorld... functions
+ behind=infront=NULL; // Set pointers to other worlds to NULL
+ toLeft=toRight=NULL; // to avoid accidental calls to goWorld... functions
+ //peeps=(Entity **)calloc(WORLD_ENTITY_MAX+1,sizeof(Entity *)); // peeps[0] is reserved for the player when detect() is called
+ //peepCount=0;
}
World::~World(void){
free(line); // Free (de-allocate) the array 'line'
+ //free(peeps); // same for the entity array
}
void World::draw(vec2 *vec){
@@ -78,7 +83,7 @@ LOOP2: // Draw each world
cline=current->line; // 'cline' and 'cx_start' only exist to make the for loop clear (and maybe make it faster)
cx_start=current->x_start;
glBegin(GL_QUADS);
- for(i=i;i<ie;i++){ // For lines in array 'line' from 'i' to 'ie'
+ for(i=i;i<ie-GEN_INC;i++){ // For lines in array 'line' from 'i' to 'ie'
cline[i].y+=(yoff-DRAW_Y_OFFSET); // 'yoff' is always one incrementation ahead of what it should be
safeSetColor(shade,200+shade,shade); // Safely set the grass color
glVertex2i(cx_start+i*HLINE ,cline[i].y); // Draw the grass area of the line
@@ -101,24 +106,38 @@ LOOP2: // Draw each world
}else{ // Otherwise reset static values and return
yoff=DRAW_Y_OFFSET;
shade=0;
+ /*if(peepCount){
+ for(i=1;i<peepCount;i++){
+ peeps[i]->draw();
+ }
+ }*/
}
}
-void World::detect(vec2 *v,vec2 *vel,const float width){
+void World::singleDetect(Entity *e){
unsigned int i;
- i=(v->x+width/2-x_start)/HLINE; // Calculate what line the player is currently on
- if(v->y<=line[i].y){ // Snap the player to the top of that line if the player is inside it
- vel->y=0;
- v->y=line[i].y+HLINE/2;
- }else{ // If the player is above the ground do some gravity stuff
- vel->y-=.01;
+ if(e->alive){
+ i=(e->loc.x+e->width/2-x_start)/HLINE; // Calculate what line the player is currently on
+ if(e->loc.y<=line[i].y){ // Snap the player to the top of that line if the player is inside it
+ e->vel.y=0;
+ e->loc.y=line[i].y+HLINE/2;
+ }else{ // If the player is above the ground do some gravity stuff
+ e->vel.y-=.01;
+ }
+ if(e->loc.x<x_start){ // Keep the player inside world bounds (ui.cpp handles world jumping)
+ e->vel.x=0;
+ e->loc.x=x_start+HLINE/2;
+ }else if(e->loc.x+e->width+HLINE>x_start+getWidth(this)){
+ e->vel.x=0;
+ e->loc.x=x_start+getWidth(this)-e->width-HLINE;
+ }
}
- if(v->x<x_start){ // Keep the player inside world bounds (ui.cpp handles world jumping)
- vel->x=0;
- v->x=x_start+HLINE/2;
- }else if(v->x+width+HLINE>x_start+getWidth(this)){
- vel->x=0;
- v->x=x_start+getWidth(this)-width-HLINE;
+}
+void World::detect(Player *p){
+ unsigned int i;
+ singleDetect(p);
+ for(i=0;i<=entity.size();i++){
+ singleDetect(entity[i]);
}
}
@@ -135,34 +154,42 @@ void World::addLayer(unsigned int width){
behind->infront=this;
}
-World *World::goWorldLeft(vec2 *loc,const float width){
- if(toLeft&&loc->x<x_start+HLINE*10){
- loc->x=toLeft->x_start+getWidth(toLeft)-HLINE*10;
- loc->y=toLeft->line[0].y;
+World *World::goWorldLeft(Player *p){
+ if(toLeft&&p->loc.x<x_start+HLINE*10){
+ p->loc.x=toLeft->x_start+getWidth(toLeft)-HLINE*10;
+ p->loc.y=toLeft->line[0].y;
return toLeft;
}
return this;
}
-World *World::goWorldRight(vec2 *loc,const float width){
- if(toRight&&loc->x+width>x_start+getWidth(this)-HLINE*10){
- loc->x=toRight->x_start+HLINE*10;
- loc->y=toRight->line[toRight->lineCount-GEN_INC-1].y;
+World *World::goWorldRight(Player *p){
+ if(toRight&&p->loc.x+p->width>x_start+getWidth(this)-HLINE*10){
+ p->loc.x=toRight->x_start+HLINE*10;
+ p->loc.y=toRight->line[toRight->lineCount-GEN_INC-1].y;
return toRight;
}
return this;
}
-World *World::goWorldBack(vec2 *loc,const float width){
- if(behind&&loc->x>(int)(0-getWidth(behind)/2)&&loc->x<getWidth(behind)/2){
+World *World::goWorldBack(Player *p){
+ if(behind&&p->loc.x>(int)(0-getWidth(behind)/2)&&p->loc.x<getWidth(behind)/2){
return behind;
}
return this;
}
-World *World::goWorldFront(vec2 *loc,const float width){
- if(infront&&loc->x>(int)(0-getWidth(infront)/2)&&loc->x<getWidth(infront)/2){
+World *World::goWorldFront(Player *p){
+ if(infront&&p->loc.x>(int)(0-getWidth(infront)/2)&&p->loc.x<getWidth(infront)/2){
return infront;
}
return this;
}
+
+/*void World::addEntity(Entity *e){
+ if(peepCount!=WORLD_ENTITY_MAX){
+ peeps[1+peepCount++]=e; // See peeps's allocation in World() for explanation of the 1+...
+ }else{
+ std::cout<<"Warning: can't add any more entities"<<std::endl;
+ }
+}*/