/*******************************************************************************************
*
* gameLibZero 0.1 by: Luis Lopez Martinez. 28/11/2018
*
********************************************************************************************/
#include "raylib.h"
#include "chipmunk/chipmunk.h"
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <iostream>
#include <cstring>
#include <dirent.h>
#define process sprite
#define key IsKeyDown
#define rand GetRandomValue
#define images vector<Texture2D>
#define sounds vector<Sound>
#define musics vector<Music>
#define fonts vector<Font>
using namespace std;
struct mouse{
float x;
float y;
float oldx;
float oldy;
bool wheelUp = false;
bool wheelDown = false;
int wheel = 0;
bool left = false;
bool right = false;
bool middle = false;
bool touch = false;
cpBody *body;
cpShape *shape;
Vector2 pos;
int id = -1;
}mouse;
class sprite; // clase principal de objeto para el juego..
vector<sprite*>sprites; // coleccion de sprites/procesos..
int spriteIdCounter = 0;
const int s_kill = -1; // señal que marca a un proceso para morir..
const int s_protected = -2; // señal que proteje a un proceso de la muerte..
sprite* _temporal_sprite_id_; // puntero que indica el sprite actual que está realizando operaciones.. así desde letMeAlone() puedo dejarlo vivo..
int frameCount = 0; // contador que indica los frames que han pasado desde el inicio de la ejecución del programa..
bool _signals_pending_ = false; // si se ha llamado a signal() esta variable se pone a true y al final del frame actual se hará un update de los sprites que deban morir..
const int CENTER = 4; // usado como parametro para renderizar textos..
const int LEFT = 3; // usado como parametro para renderizar textos..
const int RIGHT = 5; // usado como parametro para renderizar textos..
bool fading = false;
int fadingType = 0;
float deltaFading = 0.0f;
float alphaFading = 1.0f;
Texture2D screenFadeImage;
Color _FADING_COLOR_ = BLACK;
Color _BK_COLOR_ = BLACK;
void setup();
void draw();
void setMode(int, int);
void setTitle(char[]);
void setFps(int);
int fps = 60;
Texture2D loadImage(char[]);
void screenDrawText(Font, int, char[], const int, int, int, Color, float);
void screenDrawText(Font, int, int, const int, int, int, Color, float);
void screenDrawText(Font, int, float, const int, int, int, Color, float);
void screenDrawText(Font, int, double, const int, int, int, Color, float);
void screenDrawText(Font, int, bool, const int, int, int, Color, float);
void screenDrawGraphic(Texture2D, float, float, float, float, float);
// Physics world global variables..
cpSpace *space;
cpFloat timeStep = 1.0/60.0; // al setear los frames por segundo con setFps se actualiza este valor..
// Namespaces:
const int TYPE_WORLD = 1;
const int TYPE_ENTITY = 2;
// Resolución en pasos por default para el motor de física:
int timesteep_;
// Tipos de shapes:
const int TYPE_EMPTY = 0;
const int TYPE_POLY = 1;
const int TYPE_BOX = 2;
const int TYPE_CIRCLE = 3;
const int TYPE_LINE = 4;
// Tipos de materiales..
// materiales disponibles para la simulación física..
const int WOOD = 1;
const int METAL = 2;
const int STONE = 3;
const int PLASTIC = 4;
const int RUBBER = 5;
const int HUMAN = 6;
// global variables for music player control..
bool _music_play_ = false;
Music _music_play_id_;
// scrolling games gloabal variables..
Camera2D camera;
sprite* _camera_id_;
class region{
public:
float x;
float y;
float w;
float h;
region(float x_, float y_, float w_, float h_){
x = x;
y = y_;
w = w_;
h = h_;
}
};
//------------------------------------------------------------------------------------------------------
void fullscreen(){
ToggleFullscreen();
}
//------------------------------------------------------------------------------------------------------
void setCamera(sprite* s){
_camera_id_ = s;
}
//------------------------------------------------------------------------------------------------------
void setGravity(float gx, float gy){
cpVect gravity = cpv(gx, gy);
cpSpaceSetGravity(space, gravity);
}
//------------------------------------------------------------------------------------------------------
void setDamping(float damping_){
cpSpaceSetDamping(space, damping_);
}
//------------------------------------------------------------------------------------------------------
float radians(float deg){
return (deg * PI) / 180.0f;
}
//------------------------------------------------------------------------------------------------------
float degrees(float rad){
return (rad * 180.0f) / PI;
}
//------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
void _fade_instantaneo_(){
if (fadingType == -1) {
deltaFading = 0;
alphaFading = 1.0f;
fading = false;
} else if (fadingType == 1) {
deltaFading = 0;
alphaFading = 0.0f;
fading = false;
}
}
//---------------------------------------------------------------------------------
void fadeOn(int time_) {
fading = true;
fadingType = -1;
int fadingFramesLeft = int((time_ * fps) / 1000);
deltaFading = (1.0f / fadingFramesLeft);
if(time_ == 0){
_fade_instantaneo_();
}
}
//---------------------------------------------------------------------------------
void fadeOff(int time_) {
fading = true;
fadingType = 1;
int fadingFramesLeft = int((time_ * fps) / 1000);
deltaFading = (1.0f / fadingFramesLeft);
if(time_ == 0){
_fade_instantaneo_();
}
}
//------------------------------------------------------------------------------------------------------
void setBackgroundColor(Color c){
_BK_COLOR_ = c;
}
//------------------------------------------------------------------------------------------------------
void setFadingColor(Color c){
_FADING_COLOR_ = c;
}
//------------------------------------------------------------------------------------------------------
class sprite{
private:
bool s_kill_protected = false; // proteccion ante un s_kill..
bool live = true; // marcado para morir o vivir..
public:
bool visible = false; // indica si el grafico es visible o no..
Texture2D graph; // apunta al grafico del proceso..
float x = 0; // coordenada X del proceso..
float y = 0; // coordenada Y del proceso..
float z = 0; // indica el orden de pintado en pantalla.. zBuffer..
float size = 100; // escalado del grafico..
float sizex = 100;
float sizey = 100;
float angle = 0; // rotacion en grados del grafico del proceso..
float alpha = 255; // opacidad/transparencia del grafico..
Color _TINT_COLOR_ = WHITE; // color con el que tintar el grafico.. para hacer efectos..
int width; // ancho del grafico en pixels contemplando el escalado..
int height; // alto del grafico en pixels contemplando el escalado..
Rectangle sourceRec = { 0, 0, 0, 0 }; // rectangulo original que contiene el grafico, necesario para escalar y rotar con raylib..
Rectangle destRec = { 0, 0, 0, 0 }; // rectangulo de salida para el grafico, necesario para escalar y rotar con raylib..
Vector2 origin; // punto de rotacion y escalado del grafico..
bool origin_modificado = false; // si se usa setCenter() esta variable se pone a true..
Vector2 originPersonalizado;
Vector2 pos; // deprecated..
float scale; // deprecated..
Vector2 finalPosition; // deprecated..
bool body_created = false; // indica si el proceso tiene un cuerpo fisico creado..
cpBody *body; // apunta al cuerpo del proceso..
cpShape *shape; // apunta al shape de colision del proceso..
cpFloat radius; // indica el radio del grafico contemplando escalado si body esta definido como CIRCLE..
cpFloat mass; // masa del cuerpo del proceso..
cpFloat moment; // momento de inercia del proceso..
float density = 1.0f; // densidad base/generica del cuerpo..
int id; // identificador unico de proceso..
int liveFrames = 0; // frames que lleva vivo el proceso..
int type; // tipo de objeto.. necesario para collisionType( type_object )..
//bool s_kill_protected = false; // proteccion ante un s_kill..
//bool live = true; // marcado para morir o vivir..
float oldX, oldY; // coordenadas en el frame anterior..
bool scene = false; // indica si el proceso se renderiza teniendo en cuenta la camera2D o no..
bool xmirror = false;
bool ymirror = false;
Vector2 tiling = { 1.0f, 1.0f }; // cantidad de graficos que caben en el canvas final del grafico.. para tilear..
Vector2 offset = { 0.0f, 0.0f }; // desplazamiento del grafico dentro del canvas del propio grafico..
sprite* father; // apunta al proceso/sprite que crea a este.. se le puede llamar "padre"..
int priority = 0;
//---------------------------------------------------------------
void setLive(bool flag){
live = flag;
}
bool getLive(){
return live;
}
//---------------------------------------------------------------
void setProtec(bool flag){
s_kill_protected = flag;
}
bool getProtec(){
return s_kill_protected;
}
//---------------------------------------------------------------
void setCenter(float x, float y){
origin_modificado = true;
originPersonalizado.x = x;
originPersonalizado.y = y;
}
//---------------------------------------------------------------
sprite(){
sprites.push_back(this);
father = _temporal_sprite_id_;
id = spriteIdCounter++;
}
//---------------------------------------------------------------
virtual void frame (void) = 0; // Metodo virtual puro
//---------------------------------------------------------------
Vector2 rotate(Vector2 point, Vector2 center, float angle) {
angle = angle * (M_PI/180);
float rotatedX = cos(angle) * (point.x - center.x) - sin(angle) * (point.y-center.y) + center.x;
float rotatedY = sin(angle) * (point.x - center.x) + cos(angle) * (point.y - center.y) + center.y;
return (Vector2) {rotatedX,rotatedY};
}
//---------------------------------------------------------------
int calculateClassTypeID(){
const char* name[] = { typeid(*this).name() }; // obtener un identificador del tipo de clase derivada que instancia esta clase base..
int len = strlen(*name); // obtener largo de la cadena de texto..
int _id_ = 0; // id generado..
for(int i=0; i<len;i++){ // recorrer cadena de texto..
_id_ += ((int)name[i] - 48) * i; // crc por char.. obtener id unico por nombre..
}
return _id_;
}
//---------------------------------------------------------------
void setTintColor(Color c){
_TINT_COLOR_ = c;
}
//---------------------------------------------------------------
Color getTintColor(){
return _TINT_COLOR_;
}
//---------------------------------------------------------------
void render(){
if(liveFrames == 0){
type = calculateClassTypeID();
}
// save position for DX DY calculation..
oldX = x;
oldY = y;
// update body..
if(body_created){
cpVect vec = cpBodyGetPosition(body);
x = vec.x;
y = vec.y;
angle = degrees(cpBodyGetAngle(body));
}
if(graph.id != 0){
// calcular ancho y alto de la textura con size..
if(sizex!=100 || sizey!=100){
width = (graph.width*sizex)/100.0f;
height = (graph.height*sizey)/100.0f;
}else{
width = (graph.width*size)/100.0f;
height = (graph.height*size)/100.0f;
}
// inyectar ancho y alto sin escalar al rectangulo source del grafico..
sourceRec.x = offset.x+graph.width;
sourceRec.y = offset.y+graph.height;
sourceRec.width = (xmirror ? -graph.width*tiling.x : graph.width*tiling.x);
sourceRec.height = (ymirror ? -graph.height*tiling.y : graph.height*tiling.y);
// calcular propiedades del rectangulo destination en funcion de size..
destRec.x = x;
destRec.y = y;
destRec.width = width;
destRec.height = height;
// NOTE: Origin of the texture (rotation/scale point), it's relative to destination rectangle size
if(origin_modificado){
if(sizex!=100 || sizey!=100){
origin.x = (originPersonalizado.x*sizex)/100.0f;
origin.y = (originPersonalizado.y*sizey)/100.0f;
}else{
origin.x = (originPersonalizado.x*size)/100.0f;
origin.y = (originPersonalizado.y*size)/100.0f;
}
}else{
origin.x = width/2.0f;
origin.y = height/2.0f;
}
if(visible){
//BeginScissorMode( r->x, r->y, r->w, r->h );
DrawTexturePro(graph, sourceRec, destRec, origin, angle, Fade(_TINT_COLOR_, (1.0 * alpha) / 255.0f));
//EndScissorMode();
}
liveFrames++;
}
}
//---------------------------------------------------------------
void physicsEntityBuild(int type_, int material_){
if(body_created)return;
// prepare density parameter to post apply to shape..
switch(material_){
case WOOD:
density = 0.57f;
break;
case METAL:
density = 7.80f;
break;
case STONE:
density = 2.40f;
break;
case PLASTIC:
density = 0.95f;
break;
case RUBBER:
density = 1.70f;
break;
case HUMAN:
density = 0.95f;
break;
}
// create a body and collision shape..
switch(type_){
case TYPE_BOX:
if(sizex!=100 || sizey!=100){
width = (graph.width*sizex)/100.0f;
height = (graph.height*sizey)/100.0f;
}else{
width = (graph.width*size)/100.0f;
height = (graph.height*size)/100.0f;
}
mass = (width * height) * density;
// The moment of inertia is like mass for rotation
// Use the cpMomentFor*() functions to help you approximate it.
moment = cpMomentForBox(mass, width, height);
// The cpSpaceAdd*() functions return the thing that you are adding.
// It's convenient to create and add an object in one line.
body = cpSpaceAddBody(space, cpBodyNew(mass, moment));
cpBodySetPosition(body, cpv(x, y));
// Now we create the collision shape for the ball.
// You can create multiple collision shapes that point to the same body.
// They will all be attached to the body and move around to follow it.
shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0f));
break;
case TYPE_CIRCLE:
radius = ((graph.width/2)*size)/100.0f;
mass = cpAreaForCircle(0, radius) * density;
// The moment of inertia is like mass for rotation
// Use the cpMomentFor*() functions to help you approximate it.
moment = cpMomentForCircle(mass, 0, radius, cpvzero);
// The cpSpaceAdd*() functions return the thing that you are adding.
// It's convenient to create and add an object in one line.
body = cpSpaceAddBody(space, cpBodyNew(mass, moment));
cpBodySetPosition(body, cpv(x, y));
// Now we create the collision shape for the ball.
// You can create multiple collision shapes that point to the same body.
// They will all be attached to the body and move around to follow it.
shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero));
break;
}
body_created = true;
// apply material properties..
switch(material_){
case WOOD:
cpShapeSetFriction(shape, 0.50f);
cpShapeSetElasticity(shape, 0.17f);
break;
case METAL:
cpShapeSetFriction(shape, 0.13f);
cpShapeSetElasticity(shape, 0.17f);
break;
case STONE:
cpShapeSetFriction(shape, 0.75f);
cpShapeSetElasticity(shape, 0.05f);
break;
case PLASTIC:
cpShapeSetFriction(shape, 0.38f);
cpShapeSetElasticity(shape, 0.09f);
break;
case RUBBER:
cpShapeSetFriction(shape, 0.75f);
cpShapeSetElasticity(shape, 0.95f);
break;
case HUMAN:
cpShapeSetFriction(shape, 1.0f);
cpShapeSetElasticity(shape, 0.0f);
break;
}
cpShapeSetUserData(shape, this);
}
//---------------------------------------------------------------
void translate(){
if(!body_created)return;
}
//---------------------------------------------------------------
void addVelocity(float module_, float angle_){
if(!body_created)return;
cpVect velocidad_a_sumar;
velocidad_a_sumar.x = module_ * cos(radians(angle_));
velocidad_a_sumar.y = module_ * sin(radians(angle_));
cpVect velocidad_actual = cpBodyGetVelocity(body);
cpBodySetVelocity(body, cpvadd(velocidad_actual, velocidad_a_sumar));
}
//---------------------------------------------------------------
void addVx(float module_){
if(!body_created)return;
cpVect velocidad_a_sumar;
velocidad_a_sumar.x = module_;
velocidad_a_sumar.y = 0.0f;
cpVect velocidad_actual = cpBodyGetVelocity(body);
cpBodySetVelocity(body, cpvadd(velocidad_actual, velocidad_a_sumar));
}
//---------------------------------------------------------------
void addVy(float module_){
if(!body_created)return;
cpVect velocidad_a_sumar;
velocidad_a_sumar.x = 0.0f;
velocidad_a_sumar.y = module_;
cpVect velocidad_actual = cpBodyGetVelocity(body);
cpBodySetVelocity(body, cpvadd(velocidad_actual, velocidad_a_sumar));
}
//---------------------------------------------------------------
void brakeVelocity(float percent_){
if(!body_created)return;
cpVect vel = cpBodyGetVelocity(body);
vel.x = (vel.x * percent_) / 100.0f;
vel.y = (vel.y * percent_) / 100.0f;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void brakeVx(float percent_){
if(!body_created)return;
cpVect vel = cpBodyGetVelocity(body);
vel.x = (vel.x * percent_) / 100.0f;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void brakeVy(float percent_){
if(!body_created)return;
cpVect vel = cpBodyGetVelocity(body);
vel.y = (vel.y * percent_) / 100.0f;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void brakeAngularVelocity(float percent_){
if(!body_created)return;
cpFloat av = cpBodyGetAngularVelocity(body);
av = (av * percent_) / 100.0f;
cpBodySetAngularVelocity (body, av);
}
//---------------------------------------------------------------
cpVect getVelocity(){
if(!body_created)return cpvzero;
return cpBodyGetVelocity(body);
}
//---------------------------------------------------------------
float getVx(){
if(!body_created)return 0;
cpVect vel = cpBodyGetVelocity(body);
return vel.x;
}
//---------------------------------------------------------------
float getVy(){
if(!body_created)return 0;
cpVect vel = cpBodyGetVelocity(body);
return vel.y;
}
//---------------------------------------------------------------
void setVelocity(cpVect vel){
if(!body_created)return;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void setVelocity(float vx_, float vy_){
if(!body_created)return;
cpVect vel;
vel.x = vx_;
vel.y = vy_;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void setVelocity2(float module_, float angle_){
if(!body_created)return;
cpVect vel;
vel.x = module_ * cos(radians(-angle_));
vel.y = module_ * sin(radians(-angle_));
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void setVx(float vx_){
if(!body_created)return;
cpVect vel = cpBodyGetVelocity(body);
vel.x = vx_;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void setVy(float vy_){
if(!body_created)return;
cpVect vel = cpBodyGetVelocity(body);
vel.y = vy_;
cpBodySetVelocity(body, vel);
}
//---------------------------------------------------------------
void setAngle(float angle_){
if(!body_created)return;
cpBodySetAngle(body, radians(angle_));
}
//---------------------------------------------------------------
void addRotation(float av_){
if(!body_created)return;
cpFloat av = cpBodyGetAngularVelocity(body);
cpBodySetAngularVelocity (body, av + av_/10.0f);
}
//---------------------------------------------------------------
void setSensor(bool flag_){
if(!body_created)return;
cpShapeSetSensor(shape, flag_);
}
//---------------------------------------------------------------
void setStatic(bool static_){
if(!body_created)return;
if(static_){
cpBodySetType(body, CP_BODY_TYPE_STATIC );
} else{
cpBodySetType(body, CP_BODY_TYPE_DYNAMIC );
}
}
//---------------------------------------------------------------
bool collisionMouse(){
if(!body_created)return false;
cpContactPointSet cpContact = cpShapesCollide( shape, mouse.shape );
if(cpContact.count > 0){
return true;
} else{
return false;
}
}
//---------------------------------------------------------------
bool collisionMouse(sprite* s){
if(!body_created)return false;
cpContactPointSet cpContact = cpShapesCollide( s->shape, mouse.shape );
if(cpContact.count > 0 && liveFrames>1){
return true;
} else{
return false;
}
}
//---------------------------------------------------------------
bool collisionType(int type_){
if(!body_created)return false;
for(auto s : sprites){
if(s->type == type_){
if(s->body_created){
if(s->id != id){
cpContactPointSet cpContact = cpShapesCollide( s->shape, shape );
if(cpContact.count > 0){
return true;
}
}
}
}
}
return false;
}
//---------------------------------------------------------------
void advance(float module_, float angle_){
if(body_created){
cpVect pos = cpBodyGetPosition(body);
pos.x += module_ * cos(radians(angle_));
pos.y += module_ * sin(radians(angle_));
cpBodySetPosition(body, pos);
} else{
x += module_ * cos(radians(angle_));
y += module_ * sin(radians(angle_));
}
}
//---------------------------------------------------------------
//---------------------------------------------------------------
float getAngle(sprite* s){
return degrees(atan2( s->y-y, s->x-x ));
}
//---------------------------------------------------------------
float getAngle(float xx, float yy){
if(scene){
}
return degrees(atan2( xx-y, xx-x ));
}
//---------------------------------------------------------------
bool isContact(){
float ang = 0;
}
//---------------------------------------------------------------
void setType( int collide_type_ ){
if(body_created){
cpShapeSetCollisionType(shape, collide_type_);
}
}
int getType(){
if(body_created){
return cpShapeGetCollisionType(shape);
}else{
return -1;
}
}
//---------------------------------------------------------------
//---------------------------------------------------------------
};
//------------------------------------------------------------------------------------------------------
// para poder comprobar colision de un proceso con el mouse desde otro proceso o desde el main..
bool collisionMouse(sprite* s){
if(!s->body_created)return false;
cpContactPointSet cpContact = cpShapesCollide( s->shape, mouse.shape );
if(cpContact.count > 0 && s->liveFrames>1){
return true;
} else{
return false;
}
}
//------------------------------------------------------------------------------------------------------
// para poder comprobar colision de un proceso apartir de su ID con el mouse desde otro proceso o desde el main..
bool collisionMouse(int id_){
for(auto s : sprites){
if(s->id == id_){
if(!s->body_created)return false;
cpContactPointSet cpContact = cpShapesCollide( s->shape, mouse.shape );
if(cpContact.count > 0){
return true;
}
}
}
return false;
}
//------------------------------------------------------------------------------------------------------
bool collisionType(int type_, int _id_){
sprite* tempSprite;
for(auto s : sprites){
if(s->id == _id_){
tempSprite = s;
break;
}
}
if(!tempSprite->body_created)return false;
for(auto s : sprites){
if(s->type == type_){
cpContactPointSet cpContact = cpShapesCollide( s->shape, tempSprite->shape );
if(cpContact.count > 0){
return true;
}
}
}
return false;
}
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
int main()
{
// init sound system..
InitAudioDevice();
//SetMasterVolume(1.0f);
// Initialization physics engine..
cpVect gravity = cpv(0, 100);
// Create an empty space.
space = cpSpaceNew();
cpSpaceSetGravity(space, gravity);
// Init mouse body..
mouse.body = cpSpaceAddBody(space, cpBodyNewKinematic());
mouse.shape = cpSpaceAddShape(space, cpCircleShapeNew(mouse.body, 1.0f, cpvzero));
cpShapeSetSensor(mouse.shape, true);
// Call game.cpp setup user function..
setup();
// generate image for draw screen fade..
screenFadeImage = LoadTextureFromImage( GenImageColor(GetScreenWidth(), GetScreenHeight(), _FADING_COLOR_) );
camera.target = (Vector2){ GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
camera.offset = (Vector2){ 0, 0 };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
//----------------------------------------------------------------------------------
// Update objects
//----------------------------------------------------------------------------------
// update mouse parameters..
mouse.left = IsMouseButtonDown(MOUSE_LEFT_BUTTON);
mouse.right = IsMouseButtonDown(MOUSE_RIGHT_BUTTON);
mouse.middle = IsMouseButtonDown(MOUSE_MIDDLE_BUTTON);
mouse.pos = GetMousePosition();
mouse.x = mouse.pos.x;
mouse.y = mouse.pos.y;
mouse.wheel = GetMouseWheelMove();
if(mouse.wheel > 0){
mouse.wheelUp = true;
}else if(mouse.wheel < 0){
mouse.wheelDown = true;
}
cpBodySetPosition(mouse.body, cpv(mouse.x, mouse.y));
/* PERFORM FRAME() OF PROCESSES */
/*
// Sort sprites by priority..
stable_sort( sprites.begin( ), sprites.end( ), [ ]( const auto& lhs, const auto& rhs )
{
return lhs->priority > rhs->priority;
});
// Execute frame()´s..
for(auto s : sprites){
_temporal_sprite_id_ = s;
s->frame();
}
*/
// Sort sprites..
stable_sort( sprites.begin( ), sprites.end( ), [ ]( const auto& lhs, const auto& rhs )
{
return lhs->z > rhs->z;
});
//----------------------------------------------------------------------------------
// Draw objects
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(_BK_COLOR_);
if(_music_play_){
UpdateMusicStream(_music_play_id_); // Update music buffer with new stream data
}
if(_camera_id_){
//if(_camera_id_->live){
if(_camera_id_->getLive()){
camera.offset.x = GetScreenWidth()/2 - _camera_id_->x;
camera.offset.y = GetScreenHeight()/2 - _camera_id_->y;
camera.target.x = _camera_id_->x;
camera.target.y = _camera_id_->y;
}
}
// renderizar sprites que estan en la escena 2d.. "scroll"..
BeginMode2D(camera);
for(auto s : sprites){
if(s->scene){
_temporal_sprite_id_ = s;
s->render();
s->frame();
}
}
EndMode2D();
// renderizar sprites relativos a la pantalla "no scroll"..
for(auto s : sprites){
if(!s->scene){
_temporal_sprite_id_ = s;
s->render();
s->frame();
}
}
_temporal_sprite_id_ = NULL;
draw(); // main game code call..
if (fading) {
if (fadingType == -1) {
if (alphaFading < 1.0f) {
alphaFading += deltaFading;
} else {
deltaFading = 0;
alphaFading = 1.0f;
fading = false;
fadingType = 0;
}
} else if (fadingType == 1) {
if (alphaFading > 0.0f) {
alphaFading -= deltaFading;
} else {
deltaFading = 0;
alphaFading = 0.0f;
fading = false;
fadingType = 0;
}
}
}
if(alphaFading < 1.0f){
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(_FADING_COLOR_, 1.0f-alphaFading));
}
EndDrawing();
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
// Reset mouse flags..
mouse.wheelUp = false;
mouse.wheelDown = false;
// Update all world & bodies..
cpSpaceStep(space, timeStep);
// si hay operaciones pendientes con sprites...
// esta variable se pone a true con la función signal()..
if(_signals_pending_){
// creo un vector una copia del vector sprites..
vector<sprite*>_sprites_(sprites);
// limpio a sprites..
sprites.clear();
// recorro la copia del vector original..
// por que ahora el original esta vacio..
for(auto s : _sprites_){
// si el sprite tiene que seguir vivo..
//if(s->live){
if(s->getLive()){
// lo inyecto en spites..
sprites.push_back(s);
// si tiene que morir..
} else{
// elimino su shape y body antes de que termine esta iteracion y pierda el acceso a ellos..
// el sprite en si mismo desaparecerá al perder en esta iteración a _sprites_..
if(s->body_created){
cpSpaceRemoveShape(space, s->shape);
cpShapeDestroy(s->shape);
cpShapeFree(s->shape);
cpSpaceRemoveBody(space, s->body);
cpBodyDestroy(s->body);
cpBodyFree(s->body);
}
}
}
_signals_pending_ = false;
}
frameCount++; // ha pasado un frame.. para el control de acciones repetidas en el mismo frame..
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}
//------------------------------------------------------------------------------------------------------
void setMode(int w, int h){
//SetConfigFlags(FLAG_VSYNC_HINT);
InitWindow(w, h, "gameLibZero 0.1");
}
//------------------------------------------------------------------------------------------------------
void setTitle(char titulo[]){
SetWindowTitle(titulo);
}
//------------------------------------------------------------------------------------------------------
void setFps(int fps_){
fps = fps_;
SetTargetFPS(fps);
timeStep = 1.0/(float)fps;
}
//------------------------------------------------------------------------------------------------------
void screenDrawText(Font font, int size, char texto[], const int codigo_centrado, int x, int y, Color color, float alpha){
//DrawTextEx(Font font, const char* text, Vector2 position, float fontSize, float spacing, Color tint);
Vector2 position;
float fontSize = size;
float spacing = 2;
Vector2 text_size = MeasureTextEx(font, texto, size, spacing);
position.y = y;
switch(codigo_centrado){
case (int)CENTER:
position.x = x - text_size.x/2;
break;
case (int)LEFT:
position.x = x - text_size.x;
break;
case (int)RIGHT:
position.x = x;
break;
}
float alpha_ = (1.0 * alpha) / 255.0f;
Color c = Fade(color, alpha_);
DrawTextEx(font, texto, position, fontSize, spacing, c);
}
//------------------------------------------------------------------------------------------------------
void screenDrawText(Font font, int size, int number, const int codigo_centrado, int x, int y, Color color, float alpha){
char str[10];
itoa(number, str, 10);
float alpha_ = (1.0 * alpha) / 255.0f;
Color c = Fade(color, alpha_);
screenDrawText(font, size, str, codigo_centrado, x, y, c, alpha);
}
//------------------------------------------------------------------------------------------------------
void screenDrawText(Font font, int size, float number, const int codigo_centrado, int x, int y, Color color, float alpha){
char str[10];
sprintf(str,"%f", number);
float alpha_ = (1.0 * alpha) / 255.0f;
Color c = Fade(color, alpha_);
screenDrawText(font, size, str, codigo_centrado, x, y, c, alpha);
}
//------------------------------------------------------------------------------------------------------
void screenDrawText(Font font, int size, double number, const int codigo_centrado, int x, int y, Color color, float alpha){
char str[10];
sprintf(str,"%f", number);
float alpha_ = (1.0 * alpha) / 255.0f;
Color c = Fade(color, alpha_);
screenDrawText(font, size, str, codigo_centrado, x, y, c, alpha);
}
//------------------------------------------------------------------------------------------------------
void screenDrawText(Font font, int size, bool number, const int codigo_centrado, int x, int y, Color color, float alpha){
float alpha_ = (1.0 * alpha) / 255.0f;
Color c = Fade(color, alpha_);
if(number){
screenDrawText(font, size, "true", codigo_centrado, x, y, c, alpha);
} else {
screenDrawText(font, size, "false", codigo_centrado, x, y, c, alpha);
}
}
//------------------------------------------------------------------------------------------------------
void screenDrawGraphic(Texture2D graph, float x, float y, float angle, float size, float alpha){
// calcular ancho y alto de la textura con size..
float width = (graph.width*size)/100.0f;
float height = (graph.height*size)/100.0f;
// inyectar ancho y alto sin escalar al rectangulo source del grafico..
Rectangle sourceRec;
sourceRec.x = graph.width;
sourceRec.y = graph.height;
sourceRec.width = graph.width;
sourceRec.height = graph.height;
// calcular propiedades del rectangulo destination en funcion de size..
Rectangle destRec;
destRec.x = x;
destRec.y = y;
destRec.width = width;
destRec.height = height;
// NOTE: Origin of the texture (rotation/scale point), it's relative to destination rectangle size
Vector2 origin;
origin.x = width/2.0f;
origin.y = height/2.0f;
DrawTexturePro(graph, sourceRec, destRec, origin, angle, Fade(WHITE, (1.0 * alpha) / 255.0f));
}
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
Texture2D loadImage(char fileName[]){
return LoadTexture(fileName);
}
//------------------------------------------------------------------------------------------------------
bool isFile(const char* name){
DIR* directory = opendir(name);
if(directory != NULL){
closedir(directory);
return false;
}
return true;
}
//------------------------------------------------------------------------------------------------------
void loadImages(char path_[], vector<Texture2D> *imgs_){
int i=0;
DIR *dir;
dirent *ent;
if (DIR* dir = opendir(path_)){
while (dirent* ent = readdir(dir) ){
char str[255];
strcpy(str, path_);
strcat(str, "/");
strcat(str, ent->d_name);
if(isFile(str)){
cout<<"[ITEM: "<<i<<"] "<< ent->d_name<<" loaded."<<endl;
imgs_->push_back( LoadTexture(str) );
i++;
}
}
closedir (dir);
} else{
cout<<" LoadImages ERROR!"<<endl;
}
}
//------------------------------------------------------------------------------------------------------
void loadSounds(char path_[], vector<Sound> *snds_){
int i=0;
DIR *dir;
dirent *ent;
if (DIR* dir = opendir(path_)){
while (dirent* ent = readdir(dir) ){
char str[255];
strcpy(str, path_);
strcat(str, "/");
strcat(str, ent->d_name);
if(isFile(str)){
cout<<"[ITEM: "<<i<<"] "<< ent->d_name<<" loaded."<<endl;
snds_->push_back( LoadSound(str) );
i++;
}
}
closedir (dir);
} else{
cout<<" LoadSounds ERROR!"<<endl;
}
}
//------------------------------------------------------------------------------------------------------
void loadMusics(char path_[], vector<Music> *muss_){
int i=0;
DIR *dir;
dirent *ent;
if (DIR* dir = opendir(path_)){
while (dirent* ent = readdir(dir) ){
char str[255];
strcpy(str, path_);
strcat(str, "/");
strcat(str, ent->d_name);
if(isFile(str)){
cout<<"[ITEM: "<<i<<"] "<< ent->d_name<<" loaded."<<endl;
muss_->push_back( LoadMusicStream(str) );
i++;
}
}
closedir (dir);
} else{
cout<<" LoadMusics ERROR!"<<endl;
}
}
//------------------------------------------------------------------------------------------------------
void loadFonts(char path_[], vector<Font> * fnts_){
int i=0;
DIR *dir;
dirent *ent;
if (DIR* dir = opendir(path_)){
while (dirent* ent = readdir(dir) ){
char str[255];
strcpy(str, path_);
strcat(str, "/");
strcat(str, ent->d_name);
if(isFile(str)){
cout<<"[ITEM: "<<i<<"] "<< ent->d_name<<" loaded."<<endl;
fnts_->push_back( LoadFont(str) );
i++;
}
}
closedir (dir);
} else{
cout<<" LoadMusics ERROR!"<<endl;
}
}
//------------------------------------------------------------------------------------------------------
void signal(int type_, int signal_type_){
// ponemos a true esta variable y desde el main() al final del frame actual se hará un update de
// los sprites que tengan que morir etc etc..
_signals_pending_ = true;
for(auto s: sprites){
if(s->type == type_){
switch(signal_type_){
case s_kill:
if(!s->getProtec()){
s->setLive(false);
}
break;
case s_protected:
s->setProtec(true);
break;
}
}
}
}
//------------------------------------------------------------------------------------------------------
void signal(sprite* s, int signal_type_){
// ponemos a true esta variable y desde el main() al final del frame actual se hará un update de
// los sprites que tengan que morir etc etc..
_signals_pending_ = true;
switch(signal_type_){
case s_kill:
//if(!s->s_kill_protected){
if(!s->getProtec()){
//s->live = false;
s->setLive(false);
}
break;
case s_protected:
//s->s_kill_protected = true;
s->setProtec(true);
break;
}
}
//------------------------------------------------------------------------------------------------------
void letMeAlone(){
// ponemos a true esta variable y desde el main() al final del frame actual se hará un update de
// los sprites que tengan que morir etc etc..
_signals_pending_ = true;
for(auto s: sprites){
if(s!=_temporal_sprite_id_){
if(!s->getProtec()){
s->setLive(false);
}
}
}
}
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
void playMusic(Music m){
PlayMusicStream(m);
//SetMusicVolume(m, 1.0f);
_music_play_ = true;
_music_play_id_ = m;
}
//------------------------------------------------------------------------------------------------------
void playMusic(Music m, float volume_){
PlayMusicStream(m);
SetMusicVolume(m, ((1.0f * volume_) / 255.0f));
_music_play_ = true;
_music_play_id_ = m;
}
//------------------------------------------------------------------------------------------------------
void stopMusic(Music m){
StopMusicStream(m);
_music_play_ = false;
_music_play_id_ = 0;
}
//------------------------------------------------------------------------------------------------------
void stopMusic(){
StopMusicStream(_music_play_id_);
_music_play_ = false;
_music_play_id_ = 0;
}
//------------------------------------------------------------------------------------------------------
void setMusicVolume(Music m, float volume_){
SetMusicVolume(m, ((1.0f * volume_) / 255.0f));
}
//------------------------------------------------------------------------------------------------------
void playSound(Sound s){
PlaySound(s);
}
//------------------------------------------------------------------------------------------------------
void playSound(Sound s, float volume_){
PlaySound(s);
SetSoundVolume(s, ((1.0f * volume_) / 255.0f));
}
//------------------------------------------------------------------------------------------------------
void playSound(Sound s, float volume_, float pitch_){
PlaySound(s);
SetSoundVolume(s, ((1.0f * volume_) / 255.0f));
SetSoundPitch(s, ((1.0f * pitch_) / 255.0f));
}
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------