Initial commit of LD31 release of Petite Juliet.

master
kts 2014-12-27 19:48:24 -08:00
commit cd85493495
45 changed files with 1602 additions and 0 deletions

45
Makefile 100644
View File

@ -0,0 +1,45 @@
BITS ?= $(shell getconf LONG_BIT)
ifeq ($(BITS),64)
CXXFLAGS=-m64
LDFLAGS=-m64
LIB_DIR=lib64
else
CXXFLAGS=-m32
LDFLAGS=-m32
LIB_DIR=lib
endif
CXX=g++
DEBUG=-g
CXXFLAGS+=$(DEBUG) -Wall `sdl2-config --cflags` -c
#LDFLAGS+=-Wall `sdl2-config --libs` -lSDL2_image -lSDL2_mixer -lGLEW -lGL
#LDFLAGS+= -Wall -L/usr/$(LIB_DIR) -Wl,-rpath=$(LIB_DIR)/ -lSDL2 -lpthread -Wl,--no-undefined -lm -ldl -lpthread -lrt -Wl,-Bstatic -lSDL2_image -lSDL2_mixer -lGLEW -Wl,-Bdynamic -lGL
LDFLAGS+= -Wall -L/export/home/kts/Devel/sdl/$(LIB_DIR) -Wl,-rpath=$(LIB_DIR)/ -lSDL2 -lpthread -Wl,--no-undefined -lm -ldl -lpthread -lrt -Wl,-Bstatic -lSDL2_image -lSDL2_mixer -lGLEW -Wl,-Bdynamic -lGL
VPATH=src
BINARY=juliet$(BITS)
OBJ=main.o v_common.o a_common.o g_common.o shader.o texture.o World.o Sprite.o Entity.o Juliet.o Enemy.o game.o
OBJ_DIR=src/obj
$(BINARY): $(patsubst %,$(OBJ_DIR)/%,$(OBJ))
$(CXX) $^ -o $@ $(LDFLAGS)
release:
make clean
BITS=32 make install
make clean
BITS=64 make install
install: $(BINARY)
mkdir -p build/
mkdir -p build/$(LIB_DIR)/
cp -f /usr/$(LIB_DIR)/libpng14.so.14.12.0 build/$(LIB_DIR)/libpng14.so.14
cp -f /usr/$(LIB_DIR)/libSDL2-2.0.so.0.2.1 build/$(LIB_DIR)/libSDL2-2.0.so.0
cp -p $(BINARY) build/
cp -rf gfx/ build/
cp -rf sfx/ build/
cp -rf shaders build/
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
clean:
rm -f $(OBJ_DIR)/*.o && rm -f $(BINARY)

BIN
gfx/doubt.ase 100644

Binary file not shown.

BIN
gfx/doubt.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
gfx/health.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

BIN
gfx/juliet.ase 100644

Binary file not shown.

BIN
gfx/juliet.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

BIN
gfx/screens.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
gfx/waves.ase 100644

Binary file not shown.

BIN
gfx/waves.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
gfx/world.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

BIN
sfx/hit.wav 100644

Binary file not shown.

BIN
sfx/jump.wav 100644

Binary file not shown.

BIN
sfx/kick.wav 100644

Binary file not shown.

BIN
sfx/punch.wav 100644

Binary file not shown.

BIN
sfx/whoosh.wav 100644

Binary file not shown.

BIN
sfx/wiff.wav 100644

Binary file not shown.

View File

@ -0,0 +1,9 @@
#version 120
// uniforms
uniform sampler2D texture_sampler;
// input
varying vec2 frag_uv;
void main() {
gl_FragColor = texture2D(texture_sampler, frag_uv);
}

View File

@ -0,0 +1,15 @@
#version 120
// input
uniform vec2 resolution; // display resolution
attribute vec3 vp; // vertex position
uniform vec2 vp_offset; // vertex offset (draw position)
attribute vec2 uv; // UV map
uniform vec2 uv_offset; // offset within the UV map
// output
varying vec2 frag_uv;
void main() {
vec2 pos = vp.xy + vp_offset;
gl_Position = vec4(pos/resolution, 1.0, 1.0);
frag_uv = vec2(uv.s+uv_offset.x, 1.0 - uv.t+uv_offset.y);
}

View File

@ -0,0 +1,23 @@
#version 120
varying vec2 frag;
// input
uniform sampler2D texture_sampler;
uniform vec2 seed;
uniform int iteration;
void main() {
vec2 z = frag;
int i;
for (i = 0; i < iteration; i++) {
float x = (z.x * z.x - z.y * z.y) + seed.x;
float y = (z.y * z.x + z.x * z.y) + seed.y;
if ((x * x + y * y) > 4.0) break;
z.x = x;
z.y = y;
}
if (i == iteration) {
discard;
} else {
gl_FragColor = texture2D(texture_sampler, vec2(float(i)) / 100.0, 0.25);
}
}

View File

@ -0,0 +1,12 @@
#version 120
// input
attribute vec2 vp;
uniform vec2 vp_offset;
uniform vec2 size;
// output
varying vec2 frag;
void main() {
gl_Position = vec4(vp+vp_offset, 0.5, 1.0);
frag = vp/size;
}

127
src/Enemy.cpp 100644
View File

@ -0,0 +1,127 @@
#include "Enemy.hpp"
#include "g_common.hpp"
#include "a_common.hpp"
#include <stdio.h>
Enemy::Enemy() {
target = NULL;
type = ENTITY_ENEMY;
flags = ENTITY_LEFT;
max_force = 3.0f;
speed = 1.0f;
damage = 1;
}
Enemy::~Enemy() {
}
void Enemy::doThink(int delta) {
if (target == NULL) {
std::vector<Entity*>::iterator entity_it, entity_end;
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
if ((*entity_it)->type == ENTITY_JULIET) {
target = (*entity_it);
break;
}
}
} else {
if (flags & ENTITY_DIE) {
if (sprite.frame >= 10) {
flags |= ENTITY_DESTROY;
}
} else if (flags & ENTITY_HURT) {
if (!(flags & ENTITY_HAS_HURT)) {
sprite.frame = 0;
sprite.setAnimation(2);
flags |= ENTITY_HAS_HURT;
} else {
if (sprite.frame >= 6) {
sprite.frame = 0;
sprite.setAnimation(0);
flags &= ~ENTITY_HAS_HURT;
flags &= ~ENTITY_HURT;
}
}
} else if (flags & ENTITY_ATTACK) {
if (sprite.frame == 6) { // frame 6 is hit
if (!(flags & ENTITY_HAS_HIT)) {
float diff_x = target->x - x;
float diff_y = target->y - y;
if (diff_y > -48 && diff_y < 48) {
if (diff_x > 0 && diff_x < 32) {
Mix_PlayChannel(-1, a_sfx[SFX_HIT], 0);
target->takeDamage(damage);
flags |= ENTITY_HAS_HIT;
target->addForce((float)damage*3, (float)damage*3);
} else if (diff_x <= 0 && diff_x > -32) {
Mix_PlayChannel(-1, a_sfx[SFX_HIT], 0);
target->takeDamage(damage);
flags |= ENTITY_HAS_HIT;
target->addForce(-(float)damage*3, (float)damage*3);
}
}
}
} else if (sprite.frame >= 10) {
sprite.setAnimation(0);
sprite.frame = 0;
flags &= ~ENTITY_ATTACK;
flags &= ~ENTITY_HAS_HIT;
frame_time = 100;
}
} else {
float diff_x = target->x - x;
float diff_y = target->y - y;
if (diff_x > -48 && diff_x < 48 && diff_y > -48 && diff_y < 48) {
sprite.setAnimation(1);
sprite.frame = 0;
frame_time = 75;
flags |= ENTITY_ATTACK;
}
if (target->x > x) {
if (!(flags & ENTITY_RIGHT)) {
flags |= ENTITY_RIGHT;
flags &= ~ENTITY_LEFT;
sprite.flipSprite();
}
if (vel_x > -max_force && vel_x < max_force) {
if (sprite.frame == 4 || sprite.frame == 9) {
addForce(speed, 0);
} else {
addForce(speed/2.0f, 0);
}
flags |= ENTITY_WALK;
}
} else if (target->x < x) {
if (!(flags & ENTITY_LEFT)) {
flags |= ENTITY_LEFT;
flags &= ~ENTITY_RIGHT;
sprite.flipSprite();
}
if (vel_x > -max_force && vel_x < max_force) {
if (sprite.frame == 4 || sprite.frame == 9) {
addForce(-speed, 0);
} else {
addForce(-(speed/2.0f), 0);
}
flags |= ENTITY_WALK;
}
}
if (target->y > y+32) {
if (!(flags & ENTITY_FALLING)) {
flags |= ENTITY_JUMP;
addForce(0, 2);
}
}
}
}
frame_elapsed += delta;
if (frame_elapsed >= frame_time) {
frame_elapsed = 0;
sprite.loopFrame();
}
if (health <= 0) {
sprite.frame = 0;
sprite.setAnimation(3);
flags |= ENTITY_DIE;
health = 100; // cheat
}
}

14
src/Enemy.hpp 100644
View File

@ -0,0 +1,14 @@
#ifndef ENEMY_HPP
#define ENEMY_HPP
#include "Entity.hpp"
class Enemy : public Entity {
public:
Enemy();
~Enemy();
void doThink(int delta);
private:
Entity *target;
};
#endif

57
src/Entity.cpp 100644
View File

@ -0,0 +1,57 @@
#include "Entity.hpp"
#include <stdlib.h>
Entity::Entity() {
frame_time = 100;
frame_elapsed = 0;
x = y = 0;
vel_x = vel_y = 0.0f;
max_force = 5.0f;
col_box = NULL;
type = ENTITY_NONE;
flags = 0;
speed = 5.0f;
health = 10.0f;
damage = 0;
}
Entity::~Entity() {
if (col_box != NULL) free(col_box);
}
void Entity::setSprite(Sprite new_sprite) {
sprite = new_sprite;
if (col_box != NULL) free(col_box);
col_box = (float*)malloc(4*sprite.width*sprite.height*sizeof(float));
}
void Entity::addForce(float x_, float y_) {
//if (vel_x + x_ <= max_force) {
vel_x += x_;
//} else {
//vel_x = max_force;
//}
// if (vel_y + y_ <= max_force) {
vel_y += y_;
// } else {
// vel_y = max_force;
// }
}
void Entity::setPosition(float x_, float y_) {
x = x_;
y = y_;
}
void Entity::doThink(int delta) {
}
float Entity::checkCol(int x, int y, int component) {
if (x < 0 || y < 0) return 0.0f;
int pos = y*sprite.height+x+component;
return(col_box[pos]);
}
void Entity::takeDamage(int damage) {
health -= damage;
flags |= ENTITY_HURT;
sprite.frame = 0;
}
bool destroyEntity(Entity *entity) {
if (entity->flags & ENTITY_DESTROY) return true;
return false;
}

54
src/Entity.hpp 100644
View File

@ -0,0 +1,54 @@
#ifndef ENTITY_HPP
#define ENTITY_HPP
#include "Sprite.hpp"
#define ENTITY_NONE 0
#define ENTITY_JULIET 1
#define ENTITY_ENEMY 2
#define ENTITY_NONE 0
#define ENTITY_STAND 1
#define ENTITY_WALK 2
#define ENTITY_LEFT 4
#define ENTITY_RIGHT 8
#define ENTITY_ATTACK 16
#define ENTITY_JUMP 32
#define ENTITY_ATTACK2 64
#define ENTITY_FALLING 128
#define ENTITY_HAS_HIT 256
#define ENTITY_HURT 512
#define ENTITY_HAS_HURT 1024
#define ENTITY_CAN_JUMP 2048
#define ENTITY_DESTROY 4096
#define ENTITY_DIE 8192
class Entity {
protected:
public:
int frame_time;
int frame_elapsed;
Sprite sprite;
Entity();
~Entity();
int type;
int flags;
void setSprite(Sprite new_sprite);
virtual void doThink(int delta);
void setPosition(float x, float y);
void addForce(float x_, float y_);
float checkCol(int x, int y, int component);
virtual void takeDamage(int damage);
float vel_x;
float vel_y;
float x;
float y;
float pos[18]; // okay, this is what we get for not using matrices.
float *col_box;
float max_force; // self-applied force only applies up to this
//
float speed;
float health;
int damage;
};
bool destroyEntity(Entity *entity);
#endif

275
src/Juliet.cpp 100644
View File

@ -0,0 +1,275 @@
#include "Juliet.hpp"
#include "Entity.hpp"
#include "g_common.hpp"
#include "a_common.hpp"
#include <stdio.h>
Juliet::Juliet() {
frame_time = 75;
state = 0;
flags = ENTITY_LEFT;
state = ENTITY_STAND;
max_force = 4.0f;
speed = 4.0f;
damage = 2;
type = ENTITY_JULIET;
health = 20.0f;
}
Juliet::~Juliet() {
}
void Juliet::setState(int new_state) {
}
void Juliet::removeState(int rem_state) {
}
void Juliet::doThink(int delta) {
frame_elapsed += delta;
if (frame_elapsed >= frame_time) {
frame_elapsed = 0;
sprite.loopFrame();
}
if (state & JULIET_VICTORY) {
sprite.setAnimation(JULIET_ANIM_VICTORY);
return;
}
if (flags & ENTITY_ATTACK) {
if (flags & ENTITY_ATTACK2) {
flags &= ~ENTITY_ATTACK2;
state &= ~JULIET_KICKING;
sprite.setAnimation(JULIET_ANIM_PUNCH);
sprite.frame = 0;
flags &= ~ENTITY_HAS_HIT;
frame_time = 75;
}
if (state & JULIET_PUNCHING) {
if (sprite.frame == 4) {
if (!(flags & ENTITY_HAS_HIT)) {
Mix_PlayChannel(-1, a_sfx[SFX_WIFF], 0);
std::vector<Entity*>::iterator entity_it, entity_end;
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
Entity *entity = (*entity_it);
if (entity->type == ENTITY_ENEMY) {
float diff_x = entity->x - x;
float diff_y = entity->y - y;
if (diff_y > -48 && diff_y < 48) {
float force = 0;
if (diff_x > 0 && diff_x < 48) {
Mix_PlayChannel(-1, a_sfx[SFX_PUNCH], 0);
entity->addForce((float)damage*2, (float)damage*2);
entity->takeDamage(damage/2);
} else if (diff_x <= 0 && diff_x > -48) {
Mix_PlayChannel(-1, a_sfx[SFX_PUNCH], 0);
entity->addForce(-(float)damage*2, (float)damage*2);
entity->takeDamage(damage/2);
}
}
}
}
flags |= ENTITY_HAS_HIT;
}
} else if (sprite.frame == 5) {
flags &= ~ENTITY_HAS_HIT;
} else if (sprite.frame == 7) {
if (!(flags & ENTITY_HAS_HIT)) {
Mix_PlayChannel(-1, a_sfx[SFX_WIFF], 0);
std::vector<Entity*>::iterator entity_it, entity_end;
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
Entity *entity = (*entity_it);
if (entity->type == ENTITY_ENEMY) {
float diff_x = entity->x - x;
float diff_y = entity->y - y;
if (diff_y > -48 && diff_y < 48) {
float force = 0;
if (diff_x > 0 && diff_x < 48) {
Mix_PlayChannel(-1, a_sfx[SFX_PUNCH], 0);
entity->addForce((float)damage*2, (float)damage*2);
entity->takeDamage(damage/2);
} else if (diff_x <= 0 && diff_x > -48) {
Mix_PlayChannel(-1, a_sfx[SFX_PUNCH], 0);
entity->addForce(-(float)damage*2, (float)damage*2);
entity->takeDamage(damage/2);
}
}
}
}
flags |= ENTITY_HAS_HIT;
}
} else if (sprite.frame >= 10) {
state &= ~JULIET_PUNCHING;
flags &= ~ENTITY_ATTACK;
flags &= ~ENTITY_HAS_HIT;
frame_time = 100;
}
} else {
state |= JULIET_PUNCHING;
sprite.setAnimation(JULIET_ANIM_PUNCH);
sprite.frame = 0;
frame_time = 75;
}
}
if (flags & ENTITY_ATTACK2) {
if (flags & ENTITY_ATTACK) {
flags &= ~ENTITY_ATTACK;
state &= ~JULIET_PUNCHING;
sprite.setAnimation(JULIET_ANIM_KICK);
sprite.frame = 0;
frame_time = 75;
flags &= ~ENTITY_HAS_HIT;
}
if (state & JULIET_KICKING) {
if (sprite.frame == 5) {
if (!(flags & ENTITY_HAS_HIT)) {
Mix_PlayChannel(-1, a_sfx[SFX_WHOOSH], 0);
std::vector<Entity*>::iterator entity_it, entity_end;
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
Entity *entity = (*entity_it);
if (entity->type == ENTITY_ENEMY) {
float diff_x = entity->x - x;
float diff_y = entity->y - y;
if (diff_y > -48 && diff_y < 48) {
float force = 0;
if (diff_x > 0 && diff_x < 60) {
Mix_PlayChannel(-1, a_sfx[SFX_KICK], 0);
entity->addForce((float)damage*4, (float)damage*4);
entity->takeDamage(damage);
} else if (diff_x <= 0 && diff_x > -60) {
Mix_PlayChannel(-1, a_sfx[SFX_KICK], 0);
entity->addForce(-(float)damage*4, (float)damage*4);
entity->takeDamage(damage);
}
}
}
}
flags |= ENTITY_HAS_HIT;
}
} else if (sprite.frame >= 10) {
state &= ~JULIET_KICKING;
flags &= ~ENTITY_ATTACK2;
flags &= ~ENTITY_HAS_HIT;
frame_time = 100;
}
} else {
state |= JULIET_KICKING;
sprite.setAnimation(JULIET_ANIM_KICK);
sprite.frame = 0;
frame_time = 75;
}
}
if ((flags & ENTITY_JUMP) && (flags & ENTITY_CAN_JUMP)) {
if (!(state & JULIET_PUNCHING) && !(state & JULIET_KICKING)) {
sprite.setAnimation(JULIET_ANIM_JUMP);
}
if (!(state & JULIET_HOLD_JUMP)) {
if (sprite.frame == 2) {
addForce(0, speed*3);
Mix_PlayChannel(-1, a_sfx[SFX_JUMP], 0);
if (state & JULIET_LEFT) {
addForce(-speed/2, 0);
} else if (state & JULIET_RIGHT) {
addForce(speed/2, 0);
}
flags &= ~ENTITY_CAN_JUMP;
flags &= ~ENTITY_JUMP;
flags |= ENTITY_FALLING;
} else if (sprite.frame >= 9) {
flags &= ~ENTITY_JUMP;
flags &= ~ENTITY_CAN_JUMP;
}
}
} else if (flags & ENTITY_FALLING) {
if (!(state & JULIET_PUNCHING) && !(state & JULIET_KICKING)) {
sprite.setAnimation(JULIET_ANIM_JUMP);
if (sprite.frame < 4) {
sprite.frame = 4;
} else if (sprite.frame > 7) {
sprite.frame = 4;
}
}
flags &= ~ENTITY_JUMP;
if (state & JULIET_LEFT) {
addForce(-speed/2, 0);
} else if (state & JULIET_RIGHT) {
addForce(speed/2, 0);
}
} else if (flags & ENTITY_HURT) {
flags &= ~ENTITY_JUMP;
flags &= ~ENTITY_HAS_HIT;
flags &= ~ENTITY_ATTACK;
flags &= ~ENTITY_ATTACK2;
state &= ~JULIET_PUNCHING;
state &= ~JULIET_KICKING;
sprite.setAnimation(JULIET_ANIM_HURT);
frame_time = 25;
if (sprite.frame >= 6) {
flags &= ~ENTITY_HURT;
sprite.frame = 0;
frame_time = 100;
}
} else if (flags & ENTITY_WALK) {
if (!(state & JULIET_PUNCHING) && !(state & JULIET_KICKING)) {
sprite.setAnimation(JULIET_ANIM_WALK);
}
if (flags & ENTITY_LEFT) {
if (vel_x > -max_force && vel_x < max_force) {
if (sprite.frame == 4 || sprite.frame == 9) {
addForce(-speed, 0);
} else {
addForce(-(speed/2), 0);
}
}
} else if (flags & ENTITY_RIGHT) {
if (vel_x > -max_force && vel_x < max_force) {
if (sprite.frame == 4 || sprite.frame == 9) {
addForce(speed, 0);
} else {
addForce((speed/2), 0);
}
}
}
} else {
if (!(state & JULIET_PUNCHING) && !(state & JULIET_KICKING)) {
sprite.setAnimation(JULIET_ANIM_STAND);
}
}
if (state & JULIET_JUMP && flags & ENTITY_CAN_JUMP) {
flags |= ENTITY_JUMP;
sprite.frame = 0;
if (!(state & JULIET_HOLD_JUMP)) {
state |= JULIET_HOLD_JUMP;
}
} else if (state & JULIET_HOLD_JUMP && (flags & ENTITY_CAN_JUMP)) {
state &= ~JULIET_HOLD_JUMP;
}
if (state & JULIET_LEFT) {
if (!(flags & ENTITY_LEFT)) {
sprite.flipSprite();
flags |= ENTITY_LEFT;
flags &= ~ENTITY_RIGHT;
}
if (!(flags & ENTITY_FALLING)) {
flags |= ENTITY_WALK;
}
} else {
if (!(state & JULIET_RIGHT)) flags &= ~ENTITY_WALK;
}
if (state & JULIET_RIGHT) {
if (!(flags & ENTITY_RIGHT)) {
sprite.flipSprite();
flags |= ENTITY_RIGHT;
flags &= ~ENTITY_LEFT;
}
if (!(flags & ENTITY_FALLING)) {
flags |= ENTITY_WALK;
}
} else {
if (!(state & JULIET_LEFT)) flags &= ~ENTITY_WALK;
}
if (state & JULIET_PUNCH) {
flags |= ENTITY_ATTACK;
} else if (state & JULIET_KICK) {
flags |= ENTITY_ATTACK2;
}
}

39
src/Juliet.hpp 100644
View File

@ -0,0 +1,39 @@
#ifndef JULIET_HPP
#define JULIET_HPP
#include "Entity.hpp"
#define JULIET_STAND 0
#define JULIET_LEFT 1
#define JULIET_RIGHT 2
#define JULIET_WALK 4
#define JULIET_JUMP 8
#define JULIET_PUNCH 16
#define JULIET_KICK 32
#define JULIET_BUSY 64
#define JULIET_ACTIVE 128
#define JULIET_FALLING 256
#define JULIET_HOLD_JUMP 512
#define JULIET_KICKING 1024
#define JULIET_PUNCHING 2048
#define JULIET_VICTORY 4096
#define JULIET_ANIM_STAND 0
#define JULIET_ANIM_WALK 1
#define JULIET_ANIM_VICTORY 2
#define JULIET_ANIM_JUMP 3
#define JULIET_ANIM_KICK 4
#define JULIET_ANIM_PUNCH 5
#define JULIET_ANIM_HURT 6
class Juliet : public Entity {
public:
Juliet();
~Juliet();
void setState(int new_state);
void removeState(int rem_state);
void doThink(int delta);
int state;
private:
};
#endif

80
src/Sprite.cpp 100644
View File

@ -0,0 +1,80 @@
#include <stdio.h>
#include "Sprite.hpp"
Sprite::Sprite(unsigned int s_cols, unsigned int s_rows, unsigned int s_width, unsigned int s_height) {
cols = s_cols;
rows = s_rows;
width = s_width;
height = s_height;
frame = animation = 0;
x = y = 0;
offset[0] = offset[1] = texture = 0;
// create the sprite quad
float fwidth = s_width;
float fheight = s_height;
quad[0] = -fwidth; quad[1] = -fheight; quad[2] = 0.0f;
quad[3] = fwidth; quad[4] = -fheight; quad[5] = 0.0f;
quad[6] = -fwidth; quad[7] = fheight; quad[8] = 0.0f;
quad[9] = fwidth; quad[10] = fheight; quad[11] = 0.0f;
quad[12] = fwidth; quad[13] = -fheight; quad[14] = 0.0f;
quad[15] = -fwidth; quad[16] = fheight; quad[17] = 0.0f;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
// get our sprite texture UV out of spritesheet
sprite_w = fwidth/(float)(width*cols);
sprite_h = fheight/(float)(height*rows);
quad_uv[0] = 0.0; quad_uv[1] = 0.0;
quad_uv[2] = sprite_w; quad_uv[3] = 0.0;
quad_uv[4] = 0.0; quad_uv[5] = sprite_h;
quad_uv[6] = sprite_w; quad_uv[7] = sprite_h;
quad_uv[8] = sprite_w; quad_uv[9] = 0.0;
quad_uv[10] = 0.0; quad_uv[11] = sprite_h;
glGenBuffers(1, &uv);
glBindBuffer(GL_ARRAY_BUFFER, uv);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad_uv), quad_uv, GL_STATIC_DRAW);
}
Sprite::~Sprite() {
}
void Sprite::setFrame(unsigned int new_frame) {
if (new_frame > cols) {
new_frame = cols;
} else if (new_frame < 0) {
new_frame = 0;
}
frame = new_frame;
offset[0] = (float)frame * sprite_w;
}
void Sprite::incFrame() {
if (frame+1 < cols) frame++;
offset[0] = (float)frame * sprite_w;
}
void Sprite::decFrame() {
if ((int)frame-1 >= 0) frame--;
offset[0] = (float)frame * sprite_w;
}
void Sprite::loopFrame() {
if (frame+1 < cols) frame++;
else frame = 0;
offset[0] = (float)frame * sprite_w;
}
void Sprite::setAnimation(unsigned int new_animation) {
if (new_animation >= rows) {
new_animation = rows;
} else if ((int)new_animation <= 0) {
new_animation = 0;
}
animation = new_animation+1;
offset[1] = (float)animation * sprite_h;
}
void Sprite::flipSprite() {
quad[0] = -quad[0];
quad[3] = -quad[3];
quad[6] = -quad[6];
quad[9] = -quad[9];
quad[12] = -quad[12];
quad[15] = -quad[15];
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
}

39
src/Sprite.hpp 100644
View File

@ -0,0 +1,39 @@
#ifndef SPRITE_HPP
#define SPRITE_HPP
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#else
#include <GL/glew.h>
#endif
class Sprite {
private:
unsigned int x; // selected col (x * width)
unsigned int y; // selected row (y * height)
float sprite_w; // sprite's width in UV terms
float sprite_h; // sprite's height in UV terms
// this is dumb, but let's have mock vec2s for GL
float quad[18]; // quad dimensions (width/max_width)
float quad_uv[12]; // uv map
public:
unsigned int width; // width of individual sprite
unsigned int height; // height of individual sprite
unsigned int rows; // rows in sheet
unsigned int cols; // cols in sheet
Sprite(unsigned int s_cols = 0, unsigned int s_rows = 0, unsigned int s_width= 0, unsigned int s_height = 0);
~Sprite();
void setFrame(unsigned int frame);
void setAnimation(unsigned int animation);
void incFrame();
void decFrame();
void loopFrame();
void flipSprite();
GLuint vbo; // vertex buffer object for quad
GLuint uv;
GLuint uv_offset;
GLuint texture; // texture
float offset[2]; // x and y
unsigned int frame;
unsigned int animation;
};
#endif

12
src/World.cpp 100644
View File

@ -0,0 +1,12 @@
#include "World.hpp"
World::World(int iter, float size_x_, float size_y_, float offset_x_, float offset_y_) {
iteration = iter;
size_x = size_x_;
size_y = size_y_;
offset_x = offset_x_;
offset_y = offset_y_;
}
World::~World() {
}

17
src/World.hpp 100644
View File

@ -0,0 +1,17 @@
#ifndef WORLD_HPP
#define WORLD_HPP
class World {
protected:
public:
World(int iter, float size_x_, float size_y_, float offset_x_, float offset_y_);
~World();
float seed;
int iteration;
float size_x;
float size_y;
float offset_x;
float offset_y;
};
#endif

16
src/a_common.cpp 100644
View File

@ -0,0 +1,16 @@
#include "a_common.hpp"
int a_rate = 22050;
Uint16 a_format = AUDIO_S16SYS;
int a_channels = 2;
int a_buffers = 4096;
Mix_Chunk *a_sfx[SFX_COUNT] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};

19
src/a_common.hpp 100644
View File

@ -0,0 +1,19 @@
#ifndef A_COMMON_HPP
#define A_COMMON_HPP
#include "SDL_mixer.h"
extern int a_rate;
extern Uint16 a_format;
extern int a_channels;
extern int a_buffers;
#define SFX_KICK 0
#define SFX_PUNCH 1
#define SFX_WHOOSH 2
#define SFX_JUMP 3
#define SFX_WIFF 4
#define SFX_HIT 5
#define SFX_COUNT 6
extern Mix_Chunk *a_sfx[SFX_COUNT];
#endif

20
src/g_common.cpp 100644
View File

@ -0,0 +1,20 @@
#include "g_common.hpp"
int g_running = 0;
char g_keystate[256];
int g_wave = 0;
int g_waves[8] = {
5,
10,
20,
25,
30,
35,
40,
45
};
int g_victory = 0;
std::vector<Entity*> g_entities;

20
src/g_common.hpp 100644
View File

@ -0,0 +1,20 @@
#ifndef G_COMMON_HPP
#define G_COMMON_HPP
#include <vector>
#include "Entity.hpp"
extern int g_running;
extern char g_keystate[256];
extern int g_wave;
extern int g_waves[8];
extern int g_victory;
extern std::vector<Entity*> g_entities;
#define DRAG 0.25
#define GRAVITY 0.5
#define MAX_FALL 10
#define MAX_VELOCITY 4
#endif

342
src/game.cpp 100644
View File

@ -0,0 +1,342 @@
#ifdef _WIN32
#include <SDL.h>
#else
#include <SDL2/SDL.h>
#endif
#include "game.hpp"
#include <vector>
#include <algorithm>
#include "g_common.hpp"
#include "v_common.hpp"
#include "World.hpp"
#include "Sprite.hpp"
#include "Entity.hpp"
#include "Juliet.hpp"
#include "Enemy.hpp"
int runGame() {
g_running = 1;
std::vector<World*> world;
world.push_back(new World(64, 0.40, 0.40, 0, 0));
world.push_back(new World(16, 1.20, 1.00, 0, 0));
Juliet juliet;
juliet.setSprite(Sprite(11, 7, 32, 32));
juliet.sprite.texture = v_texture_juliet;
g_entities.push_back(&juliet);
Sprite waves(1, 8, 128, 32);
waves.texture = v_texture_waves;
waves.setAnimation(0);
Sprite health(2, 2, 16, 16);
health.texture = v_texture_health;
health.setAnimation(0);
Sprite screens(1, 3, 128, 128);
screens.texture = v_texture_screens;
screens.setAnimation(0);
float max_x = (float)(v_width-16);
float min_x = -(float)(v_width-16);
float max_y = -(float)(v_height-32);
float min_y = (float)(v_height+16);
unsigned int last_time = SDL_GetTicks();
unsigned int current_time = last_time;
unsigned int delta_time = 0;
unsigned int accumulator = 0;
unsigned int last_wave = SDL_GetTicks();
unsigned int next_wave = SDL_GetTicks();
int spawn_timer = 0;
int spawn_count = 0;
while(g_running) {
last_time = current_time;
current_time = SDL_GetTicks();
delta_time = current_time - last_time;
accumulator += delta_time;
// event handling
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
g_keystate[event.key.keysym.scancode] = event.key.state;
} else if (event.type == SDL_QUIT) {
g_running = 0;
} else if (event.type == SDL_WINDOWEVENT) {
if (event.window.event == SDL_WINDOWEVENT_CLOSE) {
g_running = 0;
}
}
}
// world processing
while (accumulator >= 16) {
if (juliet.health <= 0) {
juliet.flags |= ENTITY_DESTROY;
std::vector<Entity*>::iterator entity_it, entity_end;
entity_it = std::remove_if(g_entities.begin(), g_entities.end(), destroyEntity);
g_entities.erase(entity_it, g_entities.end());
screens.setAnimation(1);
if (g_keystate[SDL_SCANCODE_SPACE] == SDL_PRESSED) {
g_wave = 0;
waves.setAnimation(0);
spawn_timer = 0;
spawn_count = 0;
g_entities.clear();
juliet = Juliet();
juliet.setSprite(Sprite(11, 7, 32, 32));
juliet.sprite.texture = v_texture_juliet;
g_entities.push_back(&juliet);
screens.setAnimation(0);
}
} else if (g_victory == 1) {
screens.setAnimation(2);
juliet.state = JULIET_VICTORY;
juliet.frame_elapsed += 16;
juliet.frame_time = 200;
if (juliet.frame_elapsed >= juliet.frame_time) {
juliet.frame_elapsed = 0;
juliet.sprite.loopFrame();
}
if (g_keystate[SDL_SCANCODE_SPACE] == SDL_PRESSED) {
g_victory = 0;
g_wave = 0;
waves.setAnimation(0);
spawn_timer = 0;
spawn_count = 0;
g_entities.clear();
juliet = Juliet();
juliet.setSprite(Sprite(11, 7, 32, 32));
juliet.sprite.texture = v_texture_juliet;
g_entities.push_back(&juliet);
screens.setAnimation(0);
}
} else {
if (g_keystate[SDL_SCANCODE_SPACE] == SDL_PRESSED) {
juliet.state |= JULIET_JUMP;
} else {
juliet.state &= ~JULIET_JUMP;
}
if (g_keystate[SDL_SCANCODE_Z] == SDL_PRESSED) {
juliet.state |= JULIET_KICK;
} else {
juliet.state &= ~JULIET_KICK;
}
if (g_keystate[SDL_SCANCODE_X] == SDL_PRESSED) {
juliet.state |= JULIET_PUNCH;
} else {
juliet.state &= ~JULIET_PUNCH;
}
if (g_keystate[SDL_SCANCODE_LEFT] == SDL_PRESSED) {
juliet.state |= JULIET_LEFT;
} else {
juliet.state &= ~JULIET_LEFT;
}
if (g_keystate[SDL_SCANCODE_RIGHT] == SDL_PRESSED) {
juliet.state |= JULIET_RIGHT;
} else {
juliet.state &= ~JULIET_RIGHT;
}
spawn_timer += 16;
if (spawn_timer >= 4000) {
if (spawn_count < g_waves[g_wave]) {
spawn_timer = 0;
Enemy *new_enemy = new Enemy();
new_enemy->setSprite(Sprite(11, 4, 32, 32));
new_enemy->sprite.texture = v_texture_doubt;
new_enemy->sprite.setAnimation(1);
g_entities.push_back(new_enemy);
spawn_count++;
} else {
if (g_wave+1 >= 8) {
if (g_entities.size() == 1) {
g_victory = 1;
}
} else {
spawn_timer = 0;
spawn_count = 0;
g_wave++;
waves.setAnimation(g_wave);
}
}
}
}
std::vector<Entity*>::iterator entity_it, entity_end;
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
Entity *entity = *entity_it;
float l = (entity->checkCol(12, 4, 0)+entity->checkCol(12, 28, 0))/2.0f;
float r = (entity->checkCol(20, 4, 0)+entity->checkCol(20, 28, 0))/2.0f;
float t = (entity->checkCol(12, 28, 0)+entity->checkCol(20, 28, 0))/2.0f;
float b = (entity->checkCol(12, 4, 0)+entity->checkCol(20, 4, 0))/2.0f;
if (l > r) entity->vel_x += r*2;
else if (r > l) entity->vel_x -= r*2;
if (b > 0.00) {
entity->vel_y += b;
}
if (b <= 0.03) {
entity->vel_y -= GRAVITY;
if (b > 0.0 && b < 0.01) {
entity->flags |= ENTITY_FALLING;
entity->flags &= ~ENTITY_CAN_JUMP;
} else {
entity->flags &= ~ENTITY_FALLING;
}
} else if (b > 0.05 && b <= 0.1) {
if (entity->vel_y < 0.0f) {
entity->vel_y /= 2;
}
entity->flags &= ~ENTITY_FALLING;
} else {
if (entity->vel_y < 0.05) entity->vel_y = 0;
entity->flags &= ~ENTITY_FALLING;
entity->flags |= ENTITY_CAN_JUMP;
}
if (entity->vel_y < 0) {
entity->vel_y = (entity->vel_y < -MAX_FALL ? -MAX_FALL : entity->vel_y);
}
if (entity->vel_x > 0) {
entity->vel_x = (entity->vel_x > MAX_VELOCITY ? MAX_VELOCITY : entity->vel_x-DRAG);
} else if (entity->vel_x < 0) {
entity->vel_x = (entity->vel_x < -MAX_VELOCITY ? -MAX_VELOCITY : entity->vel_x+DRAG);
} else {
entity->vel_x = 0;
}
float x = entity->x;
float y = entity->y;
//printf("%fvs%f %fvs%f\n", entity->y+entity->vel_y, min_y, entity->y+entity->vel_y, max_y);
if (entity->y+entity->vel_y >= max_y && entity->y+entity->vel_y <= min_y) {
y = entity->y + entity->vel_y;
}
if (entity->x+entity->vel_x >= min_x && entity->x+entity->vel_x <= max_x) {
x = entity->x + entity->vel_x;
}
entity->setPosition(x, y);
entity->doThink(16);
}
entity_it = std::remove_if(g_entities.begin(), g_entities.end(), destroyEntity);
g_entities.erase(entity_it, g_entities.end());
accumulator -= 16;
}
// 1. drawing
glViewport(0, 0, v_width, v_height);
glUniform2f(v_unif_sprite_resolution, (float)v_width, (float)v_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1.1. draw world
glUseProgram(v_program_world);
glEnableVertexAttribArray(v_attr_world_vp);
// send quad
glBindBuffer(GL_ARRAY_BUFFER, v_quad_vbo);
glVertexAttribPointer(v_attr_world_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL);
std::vector<World*>::iterator world_it, world_end;
for (world_it = world.begin(), world_end = world.end(); world_it != world_end; ++world_it) {
World *werld = *world_it;
// send seed
float t = (float)SDL_GetTicks() / 10000.0f;
float seed_x = (sin(cos(t/10)*10) + cos(t*2.0)/4.0+sin(t*3.0)/6.0)*0.25;
float seed_y = (cos(sin(t/10)*10) + sin(t*2.0)/4.0+cos(t*3.0)/6.0)*0.25;
int iteration = werld->iteration;
glUniform2f(v_unif_world_seed, seed_x, seed_y);
glUniform2f(v_unif_world_size, werld->size_x, werld->size_y);
glUniform2f(v_unif_world_vp_offset, werld->offset_x, werld->offset_y);
// send iteration
glUniform1i(v_unif_world_iteration, iteration);
// send texture palette
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, v_texture_world);
glUniform1i(v_unif_world_texture, 0);
// draw quad
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glDisableVertexAttribArray(v_attr_world_vp);
// okay, this is weird, but for our entities we grab sections of the world render for pixel-based collision detection on next iteration
std::vector<Entity*>::iterator entity_it, entity_end;
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
Entity *entity = *entity_it;
int p_x = (int)((entity->x+((float)v_width))/2.0f);
int p_y = (int)((entity->y+((float)v_height)-(float)entity->sprite.height)/2.0f);
glReadPixels(p_x, p_y, (int)entity->sprite.width, (int)entity->sprite.height, GL_RGBA, GL_FLOAT, entity->col_box);
}
// 1.2. draw sprites
glUseProgram(v_program_sprite);
glEnableVertexAttribArray(v_attr_sprite_vp);
glEnableVertexAttribArray(v_attr_sprite_uv);
for (entity_it = g_entities.begin(), entity_end = g_entities.end(); entity_it != entity_end; ++entity_it) {
//send mesh
glBindBuffer(GL_ARRAY_BUFFER, (*entity_it)->sprite.vbo);
glVertexAttribPointer(v_attr_sprite_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// send uvs
glBindBuffer(GL_ARRAY_BUFFER, (*entity_it)->sprite.uv);
glVertexAttribPointer(v_attr_sprite_uv, 2, GL_FLOAT, GL_FALSE, 0, NULL);
// send uv offset
glUniform2f(v_unif_sprite_uv_offset, (*entity_it)->sprite.offset[0], (*entity_it)->sprite.offset[1]);
// set draw offset
glUniform2f(v_unif_sprite_vp_offset, (float)(int)(*entity_it)->x, (float)(int)(*entity_it)->y);
// bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, (*entity_it)->sprite.texture);
glUniform1i(v_unif_sprite_texture, 0);
// draw quad
glDrawArrays(GL_TRIANGLES, 0, 6);
}
// 1.3. draw waves UI
glBindBuffer(GL_ARRAY_BUFFER, waves.vbo);
glVertexAttribPointer(v_attr_sprite_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// send uvs
glBindBuffer(GL_ARRAY_BUFFER, waves.uv);
glVertexAttribPointer(v_attr_sprite_uv, 2, GL_FLOAT, GL_FALSE, 0, NULL);
// send uv offset
glUniform2f(v_unif_sprite_uv_offset, waves.offset[0], waves.offset[1]);
// set draw offset
glUniform2f(v_unif_sprite_vp_offset, 640-128, 480-32);
// bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, waves.texture);
glUniform1i(v_unif_sprite_texture, 0);
// draw quad
glDrawArrays(GL_TRIANGLES, 0, 6);
// 1.4. draw player health
glBindBuffer(GL_ARRAY_BUFFER, health.vbo);
glVertexAttribPointer(v_attr_sprite_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// send uvs
glBindBuffer(GL_ARRAY_BUFFER, health.uv);
glVertexAttribPointer(v_attr_sprite_uv, 2, GL_FLOAT, GL_FALSE, 0, NULL);
// send uv offset
glUniform2f(v_unif_sprite_uv_offset, health.offset[0], health.offset[1]);
// bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, health.texture);
glUniform1i(v_unif_sprite_texture, 0);
// draw quad
float i = 0;
for (i = 0; i < juliet.health; i++) {
// set draw offset
glUniform2f(v_unif_sprite_vp_offset, -((juliet.health*32)/2)+(i*32), (-480+20));
glDrawArrays(GL_TRIANGLES, 0, 6);
}
// 1.5 draw instructions
glBindBuffer(GL_ARRAY_BUFFER, screens.vbo);
glVertexAttribPointer(v_attr_sprite_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// send uvs
glBindBuffer(GL_ARRAY_BUFFER, screens.uv);
glVertexAttribPointer(v_attr_sprite_uv, 2, GL_FLOAT, GL_FALSE, 0, NULL);
// send uv offset
glUniform2f(v_unif_sprite_uv_offset, screens.offset[0], screens.offset[1]);
// bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, screens.texture);
glUniform1i(v_unif_sprite_texture, 0);
// draw quad
glUniform2f(v_unif_sprite_vp_offset, 0, (480-150));
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(v_attr_sprite_uv);
glDisableVertexAttribArray(v_attr_sprite_vp);
SDL_GL_SwapWindow(v_window);
}
return 0;
}

4
src/game.hpp 100644
View File

@ -0,0 +1,4 @@
#ifndef GAME_HPP
#define GAME_HPP
int runGame();
#endif

126
src/main.cpp 100644
View File

@ -0,0 +1,126 @@
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include "CoreFoundation/CoreFoundation.h"
#else
#include <GL/glew.h>
#endif
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
#include <stdio.h>
#include "v_common.hpp"
#include "a_common.hpp"
#include "shader.hpp"
#include "texture.hpp"
#include "game.hpp"
int main(int argc, char *argv[]) {
#ifdef __APPLE__
char path[PATH_MAX];
CFURLRef res = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
CFURLGetFileSystemRepresentation(res, TRUE, (UInt8 *)path, PATH_MAX);
CFRelease(res);
chdir(path);
#endif
printf("Petite Juliet...!\n");
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL_Init failure", SDL_GetError(), NULL);
return 1;
}
// load sdl image
int flags = IMG_INIT_PNG;
if (!(IMG_Init(flags) & flags)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "IMG_Init failure", IMG_GetError(), NULL);
return 1;
}
// load sdl mixer
flags = MIX_INIT_OGG;
if (!(Mix_Init(flags) & flags)) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Mix_Init failure", Mix_GetError(), NULL);
// let it run, I guess;
}
if (Mix_OpenAudio(a_rate, a_format, a_channels, a_buffers) != 0) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Mix_OpenAudio failure", Mix_GetError(), NULL);
// let it run, I guess;
}
// open audio files
a_sfx[SFX_KICK] = Mix_LoadWAV("sfx/kick.wav");
a_sfx[SFX_PUNCH] = Mix_LoadWAV("sfx/punch.wav");
a_sfx[SFX_WHOOSH] = Mix_LoadWAV("sfx/whoosh.wav");
a_sfx[SFX_WIFF] = Mix_LoadWAV("sfx/wiff.wav");
a_sfx[SFX_HIT] = Mix_LoadWAV("sfx/hit.wav");
a_sfx[SFX_JUMP] = Mix_LoadWAV("sfx/jump.wav");
if ((v_window = SDL_CreateWindow("Petite Juliet", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, v_width, v_height, SDL_WINDOW_OPENGL)) == NULL) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL_CreateWindow failure", SDL_GetError(), NULL);
return 1;
}
SDL_ShowCursor(0);
if ((v_glcontext = SDL_GL_CreateContext(v_window)) == NULL) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL_GL_CreateContext failure", SDL_GetError(), NULL);
return 1;
}
#ifndef __APPLE__
glewExperimental = GL_TRUE;
glewInit();
#endif
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
SDL_GL_MakeCurrent(v_window, v_glcontext);
glViewport(0, 0, v_width, v_height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SDL_GL_SwapWindow(v_window);
// compile shaders
GLuint vs, fs;
vs = compileShader("shaders/sprite_vs.glsl", GL_VERTEX_SHADER);
fs = compileShader("shaders/sprite_fs.glsl", GL_FRAGMENT_SHADER);
v_program_sprite = glCreateProgram();
glAttachShader(v_program_sprite, vs);
glAttachShader(v_program_sprite, fs);
linkProgram(v_program_sprite);
glDeleteShader(vs);
glDeleteShader(fs);
v_attr_sprite_vp = glGetAttribLocation(v_program_sprite, "vp");
v_unif_sprite_vp_offset = glGetUniformLocation(v_program_sprite, "vp_offset");
v_attr_sprite_uv = glGetAttribLocation(v_program_sprite, "uv");
v_unif_sprite_uv_offset = glGetUniformLocation(v_program_sprite, "uv_offset");
v_unif_sprite_texture = glGetUniformLocation(v_program_sprite, "texture_sampler");
v_unif_sprite_resolution = glGetUniformLocation(v_program_sprite, "resolution");
// world shader
vs = compileShader("shaders/world_vs.glsl", GL_VERTEX_SHADER);
fs = compileShader("shaders/world_fs.glsl", GL_FRAGMENT_SHADER);
v_program_world = glCreateProgram();
glAttachShader(v_program_world, vs);
glAttachShader(v_program_world, fs);
linkProgram(v_program_world);
glDeleteShader(vs);
glDeleteShader(fs);
v_attr_world_vp = glGetAttribLocation(v_program_world, "vp");
v_unif_world_vp_offset = glGetUniformLocation(v_program_world, "vp_offset");
v_unif_world_size = glGetUniformLocation(v_program_world, "size");
v_unif_world_texture = glGetUniformLocation(v_program_world, "texture_sampler");
v_unif_world_seed = glGetUniformLocation(v_program_world, "seed");
v_unif_world_iteration = glGetUniformLocation(v_program_world, "iteration");
// create our quad vertex buffer object for sprite drawing
glGenBuffers(1, &v_quad_vbo);
glBindBuffer(GL_ARRAY_BUFFER, v_quad_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(v_quad), v_quad, GL_STATIC_DRAW);
// load graphics
v_texture_juliet = loadTexture("gfx/juliet.png");
v_texture_doubt = loadTexture("gfx/doubt.png");
v_texture_world = loadTexture("gfx/world.png");
v_texture_waves = loadTexture("gfx/waves.png");
v_texture_health = loadTexture("gfx/health.png");
v_texture_screens = loadTexture("gfx/screens.png");
// load sound
// load music
runGame();
return 0;
}

58
src/shader.cpp 100644
View File

@ -0,0 +1,58 @@
#include "shader.hpp"
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
GLuint compileShader(const char *filename, GLenum type) {
std::string data;
std::ifstream filestream(filename, std::ios::in);
if(!filestream.is_open()) {
std::cerr << "compileShader: " << filename << " does not exist." << std::endl;
return 0;
}
std::string line;
while(!filestream.eof()) {
std::getline(filestream, line);
data.append(line + "\n");
}
filestream.close();
const char *buffer = data.c_str();
// create and compile shader
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &buffer, NULL);
glCompileShader(shader);
// let's do some error checking
int params = -1;
glGetShaderiv(shader, GL_COMPILE_STATUS, &params);
if (params != GL_TRUE) {
// TODO: replace with throw?
std::cout << "compileShader: shader " << shader << " failed to compile" << std::endl;
char log[2048];
int len = 0;
glGetShaderInfoLog(shader, 2048, &len, log);
std::cout << log << std::endl;
return 0;
}
// free buffer and return our shader index
std::cout << "compileShader: built " << filename << " as " << shader << std::endl;
return shader;
}
/* ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
linkProgram(GLuint program)
GLSL Shader program linking. It is left to the user to first create the program and attach the desired shaders.
```````````````````````````````````````````````````````````````` */
GLuint linkProgram(GLuint program) {
int params = -1;
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &params);
if (params != GL_TRUE) {
std::cout << "linkProgram: program " << program << " failed to link" << std::endl;
char log[2048];
int len = 0;
glGetProgramInfoLog(program, 2048, &len, log);
std::cout << log << std::endl;
return 0;
}
std::cout << "linkProgram: successfully linked " << program << std::endl;
return program;
}

17
src/shader.hpp 100644
View File

@ -0,0 +1,17 @@
/* ================================================================
Shader-related functions
````````````````
This header file and accompanying source provides functions for reading, compiling, and linking GLSL shaders.
*/
#ifndef SHADER_HPP
#define SHADER_HPP
#include <iostream>
#include <stdio.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#else
#include <GL/glew.h>
#endif
GLuint compileShader(const char *filename, GLenum type);
GLuint linkProgram(GLuint program);
#endif

51
src/texture.cpp 100644
View File

@ -0,0 +1,51 @@
#include "texture.hpp"
#if defined(_WIN32) || defined(__APPLE__)
#include <SDL.h>
#include <SDL_image.h>
#else
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#endif
GLuint loadTexture(const char *filename) {
// load image
SDL_Surface *image;
if ((image = IMG_Load(filename)) == NULL) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "loadTexture:IMG_Load", IMG_GetError(), NULL);
return 0;
}
// generate texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// apply filtering (?)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
SDL_FreeSurface(image);
return texture;
}
GLuint loadTexture1D(const char *filename) {
// load image
SDL_Surface *image;
if ((image = IMG_Load(filename)) == NULL) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "loadTexture:IMG_Load", IMG_GetError(), NULL);
return 0;
}
// generate texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_1D, texture);
// apply filtering (?)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, image->w, 0, GL_RGB, GL_UNSIGNED_BYTE, image->pixels);
SDL_FreeSurface(image);
return texture;
}

12
src/texture.hpp 100644
View File

@ -0,0 +1,12 @@
#ifndef TEXTURE_HPP
#define TEXTURE_HPP
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#else
#include <GL/glew.h>
#endif
GLuint loadTexture(const char *filename);
GLuint loadTexture1D(const char *filename);
#endif

39
src/v_common.cpp 100644
View File

@ -0,0 +1,39 @@
#include "v_common.hpp"
SDL_Window *v_window = NULL;
SDL_GLContext v_glcontext = 0;
unsigned int v_width = 640;
unsigned int v_height = 480;
GLuint v_program_world = 0;
GLuint v_attr_world_vp = 0;
GLuint v_unif_world_texture = 0;
GLuint v_unif_world_seed = 0;
GLuint v_unif_world_iteration = 0;
GLuint v_unif_world_size = 0;
GLuint v_unif_world_vp_offset = 0;
GLuint v_program_sprite = 0;
GLuint v_attr_sprite_vp = 0;
GLuint v_unif_sprite_vp_offset = 0;
GLuint v_attr_sprite_uv = 0;
GLuint v_unif_sprite_uv_offset = 0;
GLuint v_unif_sprite_texture = 0;
GLuint v_unif_sprite_resolution = 0;
GLfloat v_quad[18] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
};
GLuint v_quad_vbo = 0;
GLuint v_texture_world = 0;
GLuint v_texture_juliet = 0;
GLuint v_texture_doubt = 0;
GLuint v_texture_waves = 0;
GLuint v_texture_health = 0;
GLuint v_texture_screens = 0;

40
src/v_common.hpp 100644
View File

@ -0,0 +1,40 @@
#ifndef V_COMMON_HPP
#define V_COMMON_HPP
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#else
#include <GL/glew.h>
#endif
#include <SDL.h>
extern SDL_Window *v_window;
extern SDL_GLContext v_glcontext;
extern unsigned int v_width;
extern unsigned int v_height;
extern GLuint v_program_world;
extern GLuint v_attr_world_vp;
extern GLuint v_unif_world_texture;
extern GLuint v_unif_world_seed;
extern GLuint v_unif_world_iteration;
extern GLuint v_unif_world_size;
extern GLuint v_unif_world_vp_offset;
extern GLuint v_program_sprite;
extern GLuint v_attr_sprite_vp;
extern GLuint v_unif_sprite_vp_offset;
extern GLuint v_attr_sprite_uv;
extern GLuint v_unif_sprite_uv_offset;
extern GLuint v_unif_sprite_texture;
extern GLuint v_unif_sprite_resolution;
extern GLfloat v_quad[18];
extern GLuint v_quad_vbo;
extern GLuint v_texture_world;
extern GLuint v_texture_juliet;
extern GLuint v_texture_doubt;
extern GLuint v_texture_waves;
extern GLuint v_texture_health;
extern GLuint v_texture_screens;
#endif

20
todo.ktx 100644
View File

@ -0,0 +1,20 @@
1. frame buffer coloring object - additive layer that fades out. colors are added by players and special fx(blood,etc.)
2. throwing entities (can throw players!)
3. multiplayer, _NETWORKED_ and local
4. game is in: stages->waves
each stage is a separate color, is shown as a separate FBO in the background. when current stage end, it zooms up to replace the current stage
waves then occur
5. explosion/gore
6. multiple enemy types
also boss - each boss is a shadow of the player, probably
7. some sort of block/counter attack
8. items (parasole, etc.)
9. music and more sfx