From 26fd2a939513e3dc2d951608f089b5af52cb5e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Valor=20Mart=C3=ADnez?= Date: Thu, 18 Feb 2021 18:11:37 +0100 Subject: [PATCH] added cpp files from coffee crisis --- source/main.cpp | 130 ++ source/menu.cpp | 455 +++++++ source/menu.h | 190 +++ source/movingsprite.cpp | 132 ++ source/movingsprite.h | 77 ++ source/player.cpp | 751 +++++++++++ source/player.h | 173 +++ source/smartsprite.cpp | 228 ++++ source/smartsprite.h | 84 ++ source/sprite.cpp | 149 +++ source/sprite.h | 87 ++ source/text.cpp | 244 ++++ source/text.h | 66 + source/text2.cpp | 158 +++ source/text2.h | 102 ++ source/volcano.pas | 2704 --------------------------------------- sync.sh | 12 +- 17 files changed, 3033 insertions(+), 2709 deletions(-) create mode 100644 source/main.cpp create mode 100644 source/menu.cpp create mode 100644 source/menu.h create mode 100644 source/movingsprite.cpp create mode 100644 source/movingsprite.h create mode 100644 source/player.cpp create mode 100644 source/player.h create mode 100644 source/smartsprite.cpp create mode 100644 source/smartsprite.h create mode 100644 source/sprite.cpp create mode 100644 source/sprite.h create mode 100644 source/text.cpp create mode 100644 source/text.h create mode 100644 source/text2.cpp create mode 100644 source/text2.h delete mode 100644 source/volcano.pas diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 0000000..4d42b08 --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,130 @@ +/* +This source code copyrighted by JailDesigner (2020) +started on Castalla 15-07-2020. +Using some sample source code from Lazy Foo' Productions +*/ + +/*Descripción del enfoque utilizado para crear el juego. + +El programa contine una serie de clases/objetos básicos: la clase sprite +permite dibujar partes de un fichero png en pantalla. La clase AnimatedSprite +contiene funcionalidad adicional para crear animaciones. La clase text permite +dibujar letras de un png en pantalla a partir de una cadena de texto. La clase +menu permite crear una estructura con diferentes elementos, escribirlos en +pantalla y seleccionar uno de ellos. + +A continuación tenemos las clases enfocadas a la lógica del juego, la clase player +contiene la información del jugador, la clase balloon la de los enemigos y la +clase bullet para las balas que dispara el jugador. La clase background es +muy simple y sirve para pintar el fondo de la pantalla. Por ultimo, la clase +gamedirector es la que realiza toda la lógica y se encarga de hacer interactuar +al resto de objetos entre si. + +El objeto gamedirector tiene tres estados: titulo, juego y pausa. Segun su estado +el bucle que recorre es distinto. En el bucle juego, el objeto gamedirector +tiene un objeto jugador, un vector con los objetos globo y un vector con los +objetos bala. Se encarga de comprobar las entradas de teclado o gamepad para +cerrar la aplicacion, saltar al estado de pausa y para mover al jugador. Recorre +el vector de globos y de balas y si tienen algun tipo asignado las gestiona. +Comprueba las colisiones entre los globos y el jugador y entre las balas y los +globos. Tiene ademas un nivel de amenaza que calcula en funcion del numero de globos +en pantalla y que se va incrementando conforme aumenta la puntuación del jugador. + +Los objetos globo tienen varios contadores para alternar de un estado a otro. + +En los vectores que contienen objetos, se considera activos los objetos que tienen +un tipo asociado diferente a NO_KIND +*/ + +#include "ifdefs.h" +#include +#include +#include +#include "const.h" +#include "gamedirector.h" + +int main(int argc, char *args[]) +{ + // Inicia el generador de numeros aleatorios + srand(time(nullptr)); + + // Crea el objeto gameDirector + GameDirector *gameDirector = new GameDirector(); + + // Establece el valor de la variable con el path del ejecutable + gameDirector->setExecutablePath(args[0]); + + // Inicializa la lista de ficheros + gameDirector->setFileList(); + + // Comprueba que existen todos los ficheros + if (!gameDirector->checkFileList()) + { + return -1; + } + + // Arranca SDL y crea la ventana + if (!gameDirector->initSDL()) + { + printf("Failed to initialize!\n"); + return -1; + } + else + { + // Carga los recursos + if (!gameDirector->loadMedia(GAME_STATE_INIT)) + { + printf("Failed to load media!\n"); + } + else + { + // Inicializa el objeto gameDirector + gameDirector->init(false); + printf("Starting the game...\n\n"); + + // Mientras no se quiera salir del juego + while (!(gameDirector->getGameStatus() == GAME_STATE_QUIT)) + { + switch (gameDirector->getGameStatus()) + { + case GAME_STATE_LOGO: + gameDirector->loadMedia(GAME_STATE_LOGO); + gameDirector->runLogo(); + gameDirector->unLoadMedia(GAME_STATE_LOGO); + break; + case GAME_STATE_INTRO: + gameDirector->loadMedia(GAME_STATE_INTRO); + gameDirector->runIntro(); + gameDirector->unLoadMedia(GAME_STATE_INTRO); + break; + case GAME_STATE_TITLE: + gameDirector->loadMedia(GAME_STATE_TITLE); + gameDirector->runTitle(); + gameDirector->unLoadMedia(GAME_STATE_TITLE); + break; + case GAME_STATE_PLAYING: + gameDirector->loadMedia(GAME_STATE_PLAYING); + gameDirector->runGame(); + gameDirector->unLoadMedia(GAME_STATE_PLAYING); + break; + case GAME_STATE_GAME_OVER_SCREEN: + gameDirector->loadMedia(GAME_STATE_GAME_OVER_SCREEN); + gameDirector->runGameOverScreen(); + gameDirector->unLoadMedia(GAME_STATE_GAME_OVER_SCREEN); + break; + case GAME_STATE_INSTRUCTIONS: + gameDirector->loadMedia(GAME_STATE_INSTRUCTIONS); + gameDirector->runInstructions(); + gameDirector->unLoadMedia(GAME_STATE_INSTRUCTIONS); + break; + } + } + } + + // Libera todos los recursos y cierra SDL + delete gameDirector; + printf("Shutting down the game...\n"); + + return 0; + } +} diff --git a/source/menu.cpp b/source/menu.cpp new file mode 100644 index 0000000..a7eefc2 --- /dev/null +++ b/source/menu.cpp @@ -0,0 +1,455 @@ +#include "ifdefs.h" +#include "const.h" +#include "text.h" +#include "menu.h" + +// Constructor +Menu::Menu() +{ + init("", 0, 0, 0, nullptr, nullptr, nullptr); +} + +Menu::~Menu() +{ + mRenderer = nullptr; + mText = nullptr; +} + +// Inicializador +void Menu::init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text) +{ + // Inicia variables + mName = name; + mSelector.index = 0; + mTotalItems = 0; + mItemSelected = MENU_NO_OPTION; + mVerticalPadding = 1; + mPosX = x; + mPosY = y; + mRectBG.rect.x = 0; + mRectBG.rect.y = 0; + mRectBG.rect.w = 0; + mRectBG.rect.h = 0; + mRectBG.r = 0; + mRectBG.g = 0; + mRectBG.b = 0; + mSelector.rect.x = 0; + mSelector.rect.y = 0; + mSelector.rect.w = 0; + mSelector.rect.h = 0; + mSelector.r = 0; + mSelector.g = 0; + mSelector.b = 0; + mSelector.a = 255; + mBackgroundType = backgroundType; + mText = text; + mRenderer = renderer; + mIsCentered = false; + mAreElementsCentered = false; + mCenter = x + ((SCREEN_WIDTH - x) / 2); + mWidestItem = 0; + + // Selector + mSelector.origin = 0; + mSelector.target = 0; + mSelector.y = 0; + mSelector.numJumps = 4; + mSelector.despY = 0; + mSelector.moving = false; + + // Sprite con los graficos del selector + //mSelectorSprite.setWidth(8); + //mSelectorSprite.setHeight(8); + //mSelectorSprite.setPosX(0); + //mSelectorSprite.setPosY(0); + //mSelectorSprite.setTexture(texture); + //mSelectorSprite.setRenderer(renderer); + //mSelectorSprite.setSpriteClip(0, 0, mSelectorSprite.getWidth(), mSelectorSprite.getHeight()); + + // Elementos del menu + for (int i = 0; i < 10; i++) + { + mItem[i].label = ""; + mItem[i].w = 0; + mItem[i].h = 0; + mItem[i].x = 0; + mItem[i].y = 0; + mItem[i].hPaddingUp = 0; + mItem[i].hPaddingDown = 0; + } + + // Mueve el grafico del selector al elemento seleccionado + //moveSelectorSprite(mSelector.index); +} + +// Obtiene el nombre del menu +std::string Menu::getName() +{ + return mName; +} + +// Obtiene el valor de la variable +Uint8 Menu::getItemSelected() +{ + return mItemSelected; +} + +// Mueve el grafico del selector al elemento seleccionado +/*void Menu::moveSelectorSprite(int pos) +{ + mSelector.rect.y = mItem[pos].y - 1; +}*/ + +// Actualiza la posicion y el estado del selector +void Menu::updateSelector() +{ + if (mSelector.moving) + { + mSelector.y += mSelector.despY; + if (mSelector.despY > 0) // Va hacia abajo + { + if (mSelector.y > mSelector.target) // Ha llegado al destino + { + mSelector.origin = mSelector.y = mSelector.target; + mSelector.moving = false; + } + } + if (mSelector.despY < 0) // Va hacia abajo + { + if (mSelector.y < mSelector.target) // Ha llegado al destino + { + mSelector.origin = mSelector.y = mSelector.target; + mSelector.moving = false; + } + } + mSelector.rect.y = int(mSelector.y) - 1; + } + else + { + mSelector.rect.y = int(mSelector.y) - 1; + } +} + +// Establece el origen del selector +void Menu::setSelectorOrigin(int value) +{ + mSelector.origin = value; +} + +// Establece el destino del selector +void Menu::setSelectorTarget(int value) +{ + mSelector.target = value; +} + +// Coloca el selector en una posición específica +void Menu::setSelectorPos(Uint8 index) +{ + if (index < mTotalItems) + { + mSelector.index = index; + mSelector.y = mSelector.origin = mSelector.target = mItem[mSelector.index].y; + mSelector.moving = false; + } +} + +// Obtiene la anchura del elemento más ancho del menu +Uint16 Menu::getWidestItem() +{ + Uint16 result = 0; + + // Obtenemos la anchura del item mas ancho + for (Uint8 i = 0; i < mTotalItems; i++) + { + if (mItem[i].w > result) + { + result = mItem[i].w; + } + } + + return result; +} + +// Deja el menu apuntando al primer elemento +void Menu::reset() +{ + mItemSelected = MENU_NO_OPTION; + mSelector.index = 0; + //moveSelectorSprite(mSelector.index); + mSelector.origin = mSelector.target = mSelector.y = mItem[0].y; + mSelector.moving = false; +} + +// Deja el menu sin elemento seleccionado +void Menu::deselectItem() +{ + mItemSelected = MENU_NO_OPTION; +} + +// Actualiza el menu para recolocarlo correctamente y establecer el tamaño +void Menu::reorganize() +{ + setRectSize(); + if (mIsCentered) + centerMenu(mCenter); + if (mAreElementsCentered) + centerMenuElements(); +} + +// Deja el menu apuntando al siguiente elemento +bool Menu::increaseSelectorIndex() +{ + bool success = false; + mSelector.y = mSelector.origin = mItem[mSelector.index].y; + + if (mSelector.index < (mTotalItems - 1)) + { + mSelector.index++; + success = true; + } + + mSelector.target = mItem[mSelector.index].y; + mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps; + mSelector.moving = true; + return success; +} + +// Deja el menu apuntando al elemento anterior +bool Menu::decreaseSelectorIndex() +{ + bool success = false; + mSelector.y = mSelector.origin = mItem[mSelector.index].y; + + if (mSelector.index > 0) + { + mSelector.index--; + success = true; + } + + mSelector.target = mItem[mSelector.index].y; + mSelector.despY = (mSelector.target - mSelector.origin) / mSelector.numJumps; + mSelector.moving = true; + return success; +} + +// Comprueba la entrada (teclado, gamepad) y actua en consecuencia +bool Menu::checkInput(Uint8 input) +{ + bool success = false; + switch (input) + { + case INPUT_UP: + success = decreaseSelectorIndex(); + //moveSelectorSprite(mSelector.index); + break; + case INPUT_DOWN: + success = increaseSelectorIndex(); + //moveSelectorSprite(mSelector.index); + break; + case INPUT_ACCEPT: + mItemSelected = mSelector.index; + break; + case INPUT_CANCEL: + mItemSelected = mDefaultActionWhenCancel; + break; + } + return success; +} + +// Actualiza la logica del menu +void Menu::update() +{ + updateSelector(); +} + +// Pinta el menu en pantalla +void Menu::render() +{ + // Rendereritza el fondo del menu + if (mBackgroundType == MENU_BACKGROUND_SOLID) + { + SDL_SetRenderDrawColor(mRenderer, mRectBG.r, mRectBG.g, mRectBG.b, mRectBG.a); + SDL_RenderFillRect(mRenderer, &mRectBG.rect); + } + + // Renderiza el rectangulo del selector + SDL_SetRenderDrawColor(mRenderer, mSelector.r, mSelector.g, mSelector.b, mSelector.a); + SDL_RenderFillRect(mRenderer, &mSelector.rect); + + // Renderiza el sprite del selector + //mSelectorSprite.render(); + + // Renderitza el text + for (Uint8 i = 0; i < mTotalItems; i++) + { + if (i == mSelector.index) + { + mText->writeColored(mItem[i].x, mItem[i].y, mItem[i].label, mSelector.itemR, mSelector.itemG, mSelector.itemB); + } + else + { + mText->write(mItem[i].x, mItem[i].y, mItem[i].label, 0); + } + } +} + +// Establece el rectangulo de fondo del menu y el selector +void Menu::setRectSize() +{ + Uint8 i = 0; + mRectBG.rect.w = 0; + mRectBG.rect.h = 0; + mSelector.rect.w = 0; + mSelector.rect.h = 0; + + // Obtenemos la anchura del item mas ancho y la altura de la suma de alturas de los items + for (i = 0; i < mTotalItems; i++) + { + if (mItem[i].w > mRectBG.rect.w) + { + mRectBG.rect.w = mItem[i].w; + } + mRectBG.rect.h += mItem[i].h + mItem[i].hPaddingDown; + } + + // La anchura de la cadena más larga, mas un caracter, mas la anchura del sprite del selector + mRectBG.rect.w += (mText->getSize() * 1); // + mSelectorSprite.getWidth(); + + // La altura de la suma de los items mas un caracter y menos un pixel (porque el texto en realidad es de 7 pixeles) + mRectBG.rect.h += (mText->getSize() * 1) - 1; + + // La posición X es la del menú menos la anchura del sprite del selector y menos medio caracter + mRectBG.rect.x = mPosX - (mText->getSize() / 2); // - mSelectorSprite.getWidth(); + + // La posición Y es la del menu menos la altura de medio caracter i el padding + mRectBG.rect.y = mPosY - (mText->getSize() / 2) - mVerticalPadding; + + // Establecemos los valores del rectangulo del selector a partir de los valores del rectangulo de fondo + mSelector.rect.h = (mText->getSize() * 1) + 1; + mSelector.rect.w = mRectBG.rect.w; + mSelector.rect.x = mRectBG.rect.x; +} + +// Establece el valor de la variable +void Menu::setTotalItems(int num) +{ + mTotalItems = num; +} + +// Establece el color del rectangulo de fondo +void Menu::setBackgroundColor(int r, int g, int b, int alpha) +{ + mRectBG.r = r; + mRectBG.g = g; + mRectBG.b = b; + mRectBG.a = alpha; +} + +// Establece el color del rectangulo del selector +void Menu::setSelectorColor(int r, int g, int b, int alpha) +{ + mSelector.r = r; + mSelector.g = g; + mSelector.b = b; + mSelector.a = alpha; +} + +// Establece el color del texto del selector +void Menu::setSelectorTextColor(int r, int g, int b) +{ + mSelector.itemR = r; + mSelector.itemG = g; + mSelector.itemB = b; +} + +// Centra el menu respecto un punto +void Menu::centerMenu(int value) +{ + mIsCentered = true; + mCenter = value; + + // Actualiza el rectangulo de fondo para recalcular las dimensiones + setRectSize(); + + // Obten el acho del menu + mWidestItem = getWidestItem(); + + // Establece la nueva posición centrada en funcion del elemento más ancho + mPosX = (value) - (mWidestItem / 2); + + // Reposiciona los elementos del menu + for (Uint8 i = 0; i < 10; i++) + { + mItem[i].x = mPosX; + } + + // Recalcula el rectangulo de fondo + setRectSize(); + + // Recoloca el selector + mSelector.origin = mSelector.target = mSelector.y = mItem[mSelector.index].y; + mSelector.moving = false; + //moveSelectorSprite(mSelector.index); +} + +// Centra los elementos del menu +void Menu::centerMenuElements() +{ + mAreElementsCentered = true; + + for (Uint8 i = 0; i < mTotalItems; i++) + { + //mItem[i].x = (mCenter - ((mText->lenght(mItem[i].label, 0)) / 2)); + mItem[i].x = (mCenter - (mItem[i].w / 2)); + } + + // Mueve el grafico del selector al elemento seleccionado + //moveSelectorSprite(mSelector.index); +} + +// Añade un item al menu +void Menu::addItem(std::string text, const Uint8 hPaddingUp, const Uint8 hPaddingDown) +{ + // Si es el primer item coge la posición y del propio menu + if (mTotalItems == 0) + { + mItem[mTotalItems].label = text; + mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0); + mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2); + mItem[mTotalItems].x = mPosX; + mItem[mTotalItems].y = mPosY; + mItem[mTotalItems].hPaddingUp = hPaddingUp; + mItem[mTotalItems].hPaddingDown = hPaddingDown; + } + else + { + // En caso contrario, coge la posición y a partir del elemento anterior + if (mTotalItems < 10) + { + mItem[mTotalItems].label = text; + mItem[mTotalItems].w = mText->lenght(mItem[mTotalItems].label, 0); + mItem[mTotalItems].h = mText->getSize() + (mVerticalPadding * 2); + mItem[mTotalItems].x = mPosX; + mItem[mTotalItems].y = mItem[mTotalItems - 1].y + mItem[mTotalItems - 1].h + mItem[mTotalItems - 1].hPaddingDown; + mItem[mTotalItems].hPaddingUp = hPaddingUp; + mItem[mTotalItems].hPaddingDown = hPaddingDown; + } + } + setTotalItems(mTotalItems + 1); + reorganize(); + setSelectorPos(0); +} + +// Cambia el texto de un item +void Menu::setItemCaption(Uint8 index, std::string text) +{ + mItem[index].label = text; + mItem[index].w = mText->lenght(mItem[index].label, 0); + reorganize(); +} + +// Establece el indice del itemm que se usará por defecto al cancelar el menu +void Menu::setDefaultActionWhenCancel(Uint8 item) +{ + mDefaultActionWhenCancel = item; +} diff --git a/source/menu.h b/source/menu.h new file mode 100644 index 0000000..3201c54 --- /dev/null +++ b/source/menu.h @@ -0,0 +1,190 @@ +#pragma once +#include "sprite.h" +#include "text.h" + +#ifndef MENU_H +#define MENU_H + +// Clase menu +class Menu +{ +public: + // Constructor + Menu(); + + // Destructor + ~Menu(); + + // Inicializador + void init(std::string name, int x, int y, int backgroundType, LTexture *texture, SDL_Renderer *renderer, Text *text); + + // Obtiene el nombre del menu + std::string getName(); + + // Obtiene el valor de la variable + Uint8 getItemSelected(); + + // Deja el menu apuntando al primer elemento + void reset(); + + // Deja el menu sin elemento seleccionado + void deselectItem(); + + // Comprueba la entrada (teclado, gamepad) y actua en consecuencia + bool checkInput(Uint8 input); + + // Actualiza la logica del menu + void update(); + + // Pinta el menu en pantalla + void render(); + + // Establece el color del rectangulo de fondo + void setBackgroundColor(int r, int g, int b, int alpha); + + // Establece el color del rectangulo del selector + void setSelectorColor(int r, int g, int b, int alpha); + + // Establece el color del texto del selector + void setSelectorTextColor(int r, int g, int b); + + // Centra el menu respecto a un punto + void centerMenu(int value); + + // Centra los elementos del menu + void centerMenuElements(); + + // Añade un item al menu + void addItem(std::string text, const Uint8 hPaddingUp = 0, const Uint8 hPaddingDown = 0); + + // Cambia el texto de un item + void setItemCaption(Uint8 index, std::string text); + + // Establece el indice del item que se usará por defecto al cancelar el menu + void setDefaultActionWhenCancel(Uint8 item); + +private: + // Establece el valor de la variable + void setTotalItems(int num); + + // Establece el rectangulo de fondo del menu + void setRectSize(); + + // Actualiza el menu para recolocarlo correctamente y establecer el tamaño + void reorganize(); + + // Deja el menu apuntando al siguiente elemento + bool increaseSelectorIndex(); + + // Deja el menu apuntando al elemento anterior + bool decreaseSelectorIndex(); + + // Mueve el grafico del selector al elemento seleccionado + //void moveSelectorSprite(int pos); + + // Actualiza la posicion y el estado del selector + void updateSelector(); + + // Establece el origen del selector + void setSelectorOrigin(int value); + + // Establece el destino del selector + void setSelectorTarget(int value); + + // Coloca el selector en una posición específica + void setSelectorPos(Uint8 index); + + // Obtiene la anchura del elemento más ancho del menu + Uint16 getWidestItem(); + + // Posicion X/Y del texto del primer elemento del menu + int mPosX; // En esta posición se pinta la primera letra del primer elemento + int mPosY; + + // Nombre del menu + std::string mName; + + // Numero de items del menu + Uint8 mTotalItems; + + // Item del menu que ha sido seleccionado + Uint8 mItemSelected; + + // Item del menu seleccionado cuando se cancela el menu + Uint8 mDefaultActionWhenCancel; + + // Espacio de separacion entre items + Uint8 mVerticalPadding; + + // Tipo de fondo para el menu + Uint8 mBackgroundType; + + // Sprite con los graficos del selector + //Sprite mSelectorSprite; + + struct rectangle + { + SDL_Rect rect; + Uint8 r; // Rojo + Uint8 g; // Verde + Uint8 b; // Azul + Uint8 a; // Transparencia + }; + + rectangle mRectBG; // Rectangulo de fondo del menu + + // Estructura para cada elemento del menu + struct item + { + std::string label; + int x; + int y; + Uint8 w; + Uint8 h; + Uint8 hPaddingUp; + Uint8 hPaddingDown; + }; + + item mItem[10]; + + // Texto para poder escribir los items del menu + Text *mText; + + // Puntero al renderizador de la ventana + SDL_Renderer *mRenderer; + + // Variable para saber si el menu debe estar centrado respecto a un punto + bool mIsCentered; + + // Centro del menu + int mCenter; + + // Variable para saber si los elementos van centrados + bool mAreElementsCentered; + + // Anchura del elemento más ancho + Uint16 mWidestItem; + + struct selector + { + double origin; // Coordenada de origen + double target; // Coordenada de destino + double y; // Coordenada actual + Uint8 numJumps; // Numero de pasos preestablecido para llegar al destino + double despY; // (target - origin) / numJumps + bool moving; // Indica si el selector está avanzando hacia el destino + Uint8 index; // Elemento del menu que tiene el foco + SDL_Rect rect; + Uint8 r; // Rojo + Uint8 g; // Verde + Uint8 b; // Azul + Uint8 a; // Transparencia + Uint8 itemR; // Rojo + Uint8 itemG; // Verde + Uint8 itemB; // Azul + }; + + selector mSelector; +}; + +#endif diff --git a/source/movingsprite.cpp b/source/movingsprite.cpp new file mode 100644 index 0000000..8954677 --- /dev/null +++ b/source/movingsprite.cpp @@ -0,0 +1,132 @@ +#include "const.h" +#include "movingsprite.h" +#include + +// Constructor +MovingSprite::MovingSprite() +{ + init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr); +} + +// Destructor +MovingSprite::~MovingSprite() +{ + init(0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr); +} + +// Iniciador +void MovingSprite::init(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, LTexture *texture, SDL_Renderer *renderer) +{ + // Establece el alto y el ancho del sprite + setWidth(w); + setHeight(h); + + // Establece la posición X,Y del sprite + setPosX(x); + setPosY(y); + + // Establece la velocidad X,Y del sprite + setVelX(velx); + setVelY(vely); + + // Establece la aceleración X,Y del sprite + setAccelX(accelx); + setAccelY(accely); + + // Establece la textura donde están los gráficos para el sprite + setTexture(texture); + + // Establece el renderizador + setRenderer(renderer); + + // Establece el rectangulo de donde coger la imagen + setSpriteClip(0, 0, w, h); +} + +// Mueve el sprite +void MovingSprite::move() +{ + mPosX += mVelX; + mPosY += mVelY; + + mVelX += mAccelX; + mVelY += mAccelY; +} + +// Muestra el sprite por pantalla +void MovingSprite::render() +{ + mTexture->render(mRenderer, (int)mPosX, (int)mPosY, &mSpriteClip); +} + +// Establece el valor de la variable +float MovingSprite::getPosX() +{ + return mPosX; +} + +// Establece el valor de la variable +float MovingSprite::getPosY() +{ + return mPosY; +} + +// Establece el valor de la variable +float MovingSprite::getVelX() +{ + return mVelX; +} + +// Establece el valor de la variable +float MovingSprite::getVelY() +{ + return mVelY; +} + +// Establece el valor de la variable +float MovingSprite::getAccelX() +{ + return mAccelX; +} + +// Establece el valor de la variable +float MovingSprite::getAccelY() +{ + return mAccelY; +} + +// Establece el valor de la variable +void MovingSprite::setPosX(float x) +{ + mPosX = x; +} + +// Establece el valor de la variable +void MovingSprite::setPosY(float y) +{ + mPosY = y; +} + +// Establece el valor de la variable +void MovingSprite::setVelX(float x) +{ + mVelX = x; +} + +// Establece el valor de la variable +void MovingSprite::setVelY(float y) +{ + mVelY = y; +} + +// Establece el valor de la variable +void MovingSprite::setAccelX(float x) +{ + mAccelX = x; +} + +// Establece el valor de la variable +void MovingSprite::setAccelY(float y) +{ + mAccelY = y; +} \ No newline at end of file diff --git a/source/movingsprite.h b/source/movingsprite.h new file mode 100644 index 0000000..f4bdcd6 --- /dev/null +++ b/source/movingsprite.h @@ -0,0 +1,77 @@ +#pragma once +#include "ifdefs.h" +#include "sprite.h" + +#ifndef MOVINGSPRITE_H +#define MOVINGSPRITE_H + +// Clase MovingSprite. Añade posicion y velocidad en punto flotante +class MovingSprite : public Sprite +{ +public: + // Constructor + MovingSprite(); + + // Destructor + ~MovingSprite(); + + // Iniciador + void init(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, LTexture *texture, SDL_Renderer *renderer); + + // Mueve el sprite + void move(); + + // Muestra el sprite por pantalla + void render(); + + // Obten el valor de la variable + float getPosX(); + + // Obten el valor de la variable + float getPosY(); + + // Obten el valor de la variable + float getVelX(); + + // Obten el valor de la variable + float getVelY(); + + // Obten el valor de la variable + float getAccelX(); + + // Obten el valor de la variable + float getAccelY(); + + // Establece el valor de la variable + void setPosX(float x); + + // Establece el valor de la variable + void setPosY(float y); + + // Establece el valor de la variable + void setVelX(float x); + + // Establece el valor de la variable + void setVelY(float y); + + // Establece el valor de la variable + void setAccelX(float x); + + // Establece el valor de la variable + void setAccelY(float y); + +private: + // Posición + float mPosX; + float mPosY; + + // Velocidad + float mVelX; + float mVelY; + + // Aceleración + float mAccelX; + float mAccelY; +}; + +#endif diff --git a/source/player.cpp b/source/player.cpp new file mode 100644 index 0000000..a0f86d4 --- /dev/null +++ b/source/player.cpp @@ -0,0 +1,751 @@ +#include "const.h" +#include "player.h" + +// Constructor +Player::Player() +{ + mSpriteLegs = new AnimatedSprite(); + mSpriteBody = new AnimatedSprite(); + init(0, 0, nullptr, nullptr, nullptr); +} + +// Destructor +Player::~Player() +{ + init(0, 0, nullptr, nullptr, nullptr); + mSpriteLegs = nullptr; + mSpriteBody = nullptr; + delete mSpriteLegs; + delete mSpriteBody; +} + +// Iniciador +void Player::init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer) +{ + // Inicializa variables de estado + mAlive = true; + mStatusWalking = PLAYER_STATUS_WALKING_STOP; + mStatusFiring = PLAYER_STATUS_FIRING_NO; + mInvulnerable = false; + mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER; + mExtraHit = false; + + // Establece la altura y el ancho del jugador + mWidth = 3 * BLOCK; + mHeight = 3 * BLOCK; + + // Establece la posición inicial del jugador + mPosX = x; + mPosY = y; + + // Establece el tamaño del circulo de colisión + mCollider.r = 7; + + // Actualiza la posición del circulo de colisión + shiftColliders(); + + // Establece la velocidad inicial + mVelX = 0; + mVelY = 0; + + // Establece la velocidad base + mBaseSpeed = 1.5; + + // Establece el numero inicial de vidas + mStartingLives = 3; + mLives = mStartingLives; + + // Establece la puntuación inicial + mScore = 0; + + // Establece el multiplicador de puntos inicial + mScoreMultiplier = 1.0f; + + // Inicia el contador para la cadencia de disparo + mCooldown = 10; + + // Inicia el sprite + mSpriteLegs->init(textureLegs, renderer); + mSpriteBody->init(textureBody, renderer); + + // Establece el alto y ancho del sprite + mSpriteLegs->setWidth(mWidth); + mSpriteLegs->setHeight(mHeight); + + mSpriteBody->setWidth(mWidth); + mSpriteBody->setHeight(mHeight); + + // Establece la posición del sprite + mSpriteLegs->setPosX(int(mPosX)); + mSpriteLegs->setPosY(mPosY); + + mSpriteBody->setPosX(int(mPosX)); + mSpriteBody->setPosY(mPosY); + + // Inicializa las variables para la animación + mSpriteLegs->setCurrentFrame(0); + mSpriteLegs->setAnimationCounter(0); + + mSpriteBody->setCurrentFrame(0); + mSpriteBody->setAnimationCounter(0); + + // Establece el numero de frames de cada animacion + mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 4); + mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 4); + mSpriteLegs->setAnimationNumFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 4); + + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 4); + mSpriteBody->setAnimationNumFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 4); + + // Establece la velocidad de cada animación + mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_STOP, 10); + mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 5); + mSpriteLegs->setAnimationSpeed(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 5); + + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_LEFT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_LEFT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP, 10); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 5); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 10); + mSpriteBody->setAnimationSpeed(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 5); + + // Establece si la animación se reproduce en bucle + mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_STOP, true); + mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_LEFT, true); + mSpriteLegs->setAnimationLoop(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, true); + + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_LEFT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_LEFT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_RIGHT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, true); + mSpriteBody->setAnimationLoop(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, true); + + // Establece los frames de cada animación + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 2, mWidth * 2, mHeight * 0, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_LEFT, 3, mWidth * 3, mHeight * 0, mWidth, mHeight); + + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 0, mWidth * 0, mHeight * 1, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 1, mWidth * 1, mHeight * 1, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 2, mWidth * 2, mHeight * 1, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_RIGHT, 3, mWidth * 3, mHeight * 1, mWidth, mHeight); + + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 0, mWidth * 0, mHeight * 2, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 1, mWidth * 1, mHeight * 2, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 2, mWidth * 2, mHeight * 2, mWidth, mHeight); + mSpriteLegs->setAnimationFrames(PLAYER_ANIMATION_LEGS_WALKING_STOP, 3, mWidth * 3, mHeight * 2, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 0, mWidth * 0, mHeight * 0, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 1, mWidth * 1, mHeight * 0, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 2, mWidth * 2, mHeight * 0, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT, 3, mWidth * 3, mHeight * 0, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 0, mWidth * 0, mHeight * 1, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 1, mWidth * 1, mHeight * 1, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 2, mWidth * 2, mHeight * 1, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT, 3, mWidth * 3, mHeight * 1, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 0, mWidth * 0, mHeight * 2, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 1, mWidth * 1, mHeight * 2, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 2, mWidth * 2, mHeight * 2, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT, 3, mWidth * 3, mHeight * 2, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 0, mWidth * 0, mHeight * 3, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 1, mWidth * 1, mHeight * 3, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 2, mWidth * 2, mHeight * 3, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT, 3, mWidth * 3, mHeight * 3, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 0, mWidth * 0, mHeight * 4, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 1, mWidth * 1, mHeight * 4, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 2, mWidth * 2, mHeight * 4, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP, 3, mWidth * 3, mHeight * 4, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 0, mWidth * 0, mHeight * 5, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 1, mWidth * 1, mHeight * 5, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 2, mWidth * 2, mHeight * 5, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP, 3, mWidth * 3, mHeight * 5, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 0, mWidth * 0, mHeight * 6, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 1, mWidth * 1, mHeight * 6, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 2, mWidth * 2, mHeight * 6, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT, 3, mWidth * 3, mHeight * 6, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 0, mWidth * 0, mHeight * 7, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 1, mWidth * 1, mHeight * 7, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 2, mWidth * 2, mHeight * 7, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT, 3, mWidth * 3, mHeight * 7, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 0, mWidth * 0, mHeight * 8, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 1, mWidth * 1, mHeight * 8, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 2, mWidth * 2, mHeight * 8, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT, 3, mWidth * 3, mHeight * 8, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 0, mWidth * 0, mHeight * 9, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 1, mWidth * 1, mHeight * 9, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 2, mWidth * 2, mHeight * 9, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT, 3, mWidth * 3, mHeight * 9, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 0, mWidth * 0, mHeight * 10, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 1, mWidth * 1, mHeight * 10, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 2, mWidth * 2, mHeight * 10, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT, 3, mWidth * 3, mHeight * 10, mWidth, mHeight); + + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 0, mWidth * 0, mHeight * 11, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 1, mWidth * 1, mHeight * 11, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 2, mWidth * 2, mHeight * 11, mWidth, mHeight); + mSpriteBody->setAnimationFrames(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT, 3, mWidth * 3, mHeight * 11, mWidth, mHeight); + + // Selecciona un frame para pintar + mSpriteLegs->setSpriteClip(mSpriteLegs->getAnimationClip(PLAYER_ANIMATION_LEGS_WALKING_STOP, 0)); + mSpriteBody->setSpriteClip(mSpriteBody->getAnimationClip(PLAYER_ANIMATION_BODY_WALKING_STOP, 0)); +} + +// Actua en consecuencia de la entrada recibida +void Player::setInput(Uint8 input) +{ + switch (input) + { + case INPUT_LEFT: + mVelX = -mBaseSpeed; + if (mExtraHit) + { + setWalkingStatus(PLAYER_STATUS_WALKING_LEFT); + } + else + { + setWalkingStatus(PLAYER_STATUS_WALKING_LEFT); + } + break; + + case INPUT_RIGHT: + mVelX = mBaseSpeed; + if (mExtraHit) + { + setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT); + } + else + { + setWalkingStatus(PLAYER_STATUS_WALKING_RIGHT); + } + break; + + case INPUT_FIRE_UP: + if (mExtraHit) + { + setFiringStatus(PLAYER_STATUS_FIRING_UP); + } + else + { + setFiringStatus(PLAYER_STATUS_FIRING_UP); + } + break; + + case INPUT_FIRE_LEFT: + if (mExtraHit) + { + setFiringStatus(PLAYER_STATUS_FIRING_LEFT); + } + else + { + setFiringStatus(PLAYER_STATUS_FIRING_LEFT); + } + break; + + case INPUT_FIRE_RIGHT: + if (mExtraHit) + { + setFiringStatus(PLAYER_STATUS_FIRING_RIGHT); + } + else + { + setFiringStatus(PLAYER_STATUS_FIRING_RIGHT); + } + break; + + default: + mVelX = 0; + if (mExtraHit) + { + setWalkingStatus(PLAYER_STATUS_WALKING_STOP); + } + else + { + setWalkingStatus(PLAYER_STATUS_WALKING_STOP); + } + break; + } +} + +// Mueve el jugador a la posición y animación que le corresponde +void Player::move() +{ + if (isAlive()) + { + // Mueve el jugador a derecha o izquierda + mPosX += mVelX; + + // Si el jugador abandona el area de juego por los laterales + if ((mPosX < PLAY_AREA_LEFT) || (mPosX + mWidth > PLAY_AREA_RIGHT)) + { + // Restaura su posición + mPosX -= mVelX; + } + + // Actualiza la posición del sprite + mSpriteLegs->setPosX(getPosX()); + mSpriteLegs->setPosY(mPosY); + + mSpriteBody->setPosX(getPosX()); + mSpriteBody->setPosY(mPosY); + } +} + +// Pinta el jugador en pantalla +void Player::render() +{ + if (isAlive()) + { + if (mInvulnerable) + { + if ((mInvulnerableTimer % 10) > 4) + { + mSpriteLegs->render(); + mSpriteBody->render(); + } + } + else + { + mSpriteLegs->render(); + mSpriteBody->render(); + } + } +} + +// Establece el estado del jugador cuando camina +void Player::setWalkingStatus(Uint8 status) +{ + // Si cambiamos de estado, reiniciamos la animación + if (mStatusWalking != status) + { + mStatusWalking = status; + mSpriteLegs->setCurrentFrame(0); + } +} + +// Establece el estado del jugador cuando dispara +void Player::setFiringStatus(Uint8 status) +{ + // Si cambiamos de estado, reiniciamos la animación + if (mStatusFiring != status) + { + mStatusFiring = status; + mSpriteBody->setCurrentFrame(0); + } +} + +// Establece la animación correspondiente al estado +void Player::setAnimation() +{ + switch (mStatusWalking) + { + case PLAYER_STATUS_WALKING_LEFT: + mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_LEFT); + switch (mStatusFiring) + { + case PLAYER_STATUS_FIRING_UP: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP); + } + + break; + + case PLAYER_STATUS_FIRING_LEFT: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT); + } + + break; + + case PLAYER_STATUS_FIRING_RIGHT: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT); + } + + break; + + case PLAYER_STATUS_FIRING_NO: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_LEFT); + } + + break; + + default: + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); + break; + } + break; + + case PLAYER_STATUS_WALKING_RIGHT: + mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_RIGHT); + switch (mStatusFiring) + { + case PLAYER_STATUS_FIRING_UP: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP); + } + + break; + + case PLAYER_STATUS_FIRING_LEFT: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT); + } + + break; + + case PLAYER_STATUS_FIRING_RIGHT: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT); + } + + break; + + case PLAYER_STATUS_FIRING_NO: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_RIGHT); + } + + break; + + default: + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); + break; + } + break; + + case PLAYER_STATUS_WALKING_STOP: + mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_STOP); + switch (mStatusFiring) + { + case PLAYER_STATUS_FIRING_UP: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_UP); + } + + break; + + case PLAYER_STATUS_FIRING_LEFT: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_LEFT); + } + + break; + + case PLAYER_STATUS_FIRING_RIGHT: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_FIRING_RIGHT); + } + + break; + + case PLAYER_STATUS_FIRING_NO: + if (mExtraHit) + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP_EXTRA_HIT); + } + else + { + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); + } + + break; + + default: + mSpriteBody->animate(PLAYER_ANIMATION_BODY_WALKING_STOP); + break; + } + break; + + default: + mSpriteLegs->animate(PLAYER_ANIMATION_LEGS_WALKING_STOP); + break; + } +} + +// Obtiene el valor de la variable +int Player::getPosX() +{ + return int(mPosX); +} + +// Obtiene el valor de la variable +int Player::getPosY() +{ + return mPosY; +} + +// Obtiene el valor de la variable +int Player::getWidth() +{ + return mWidth; +} + +// Obtiene el valor de la variable +int Player::getHeight() +{ + return mHeight; +} + +// Indica si el jugador puede disparar +bool Player::canFire() +{ + // Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador + if (mCooldown > 0) + { + return false; + } + else + { + return true; + } +} + +// Establece el valor de la variable +void Player::setFireCooldown(int time) +{ + mCooldown = time; +} + +// Actualiza el valor de la variable +void Player::updateCooldown() +{ + if (mCooldown > 0) + { + --mCooldown; + } + else + { + setFiringStatus(PLAYER_STATUS_FIRING_NO); + } +} + +// Actualiza al jugador a su posicion, animación y controla los contadores +void Player::update() +{ + move(); + setAnimation(); + shiftColliders(); + updateCooldown(); + updateInvulnerableTimer(); +} + +// Obtiene la puntuación del jugador +int Player::getScore() +{ + return mScore; +} + +// Asigna un valor a la puntuación del jugador +void Player::setScore(int score) +{ + mScore = score; +} + +// Incrementa la puntuación del jugador +void Player::addScore(int score) +{ + mScore += score; +} + +// Obtiene el valor de la variable +bool Player::isAlive() +{ + return mAlive; +} + +// Establece el valor de la variable +void Player::setAlive(bool value) +{ + mAlive = value; +} + +// Obtiene el valor de la variable +float Player::getScoreMultiplier() +{ + return mScoreMultiplier; +} + +// Establece el valor de la variable +void Player::setScoreMultiplier(float value) +{ + mScoreMultiplier = value; +} + +// Aumenta el valor de la variable hasta un máximo +void Player::incScoreMultiplier() +{ + if (mScoreMultiplier < 5.0f) + { + mScoreMultiplier += 0.1f; + } +} + +// Decrementa el valor de la variable hasta un mínimo +void Player::decScoreMultiplier() +{ + if (mScoreMultiplier > 1.0f) + { + mScoreMultiplier -= 0.1f; + } +} + +// Obtiene el valor de la variable +bool Player::isInvulnerable() +{ + return mInvulnerable; +} + +// Establece el valor de la variable +void Player::setInvulnerable(bool value) +{ + mInvulnerable = value; +} + +// Obtiene el valor de la variable +bool Player::getInvulnerableTimer() +{ + return mInvulnerableTimer; +} + +// Establece el valor de la variable +void Player::setInvulnerableTimer(Uint16 value) +{ + mInvulnerableTimer = value; +} + +// Actualiza el valor de la variable +void Player::updateInvulnerableTimer() +{ + if (mInvulnerableTimer > 0) + { + --mInvulnerableTimer; + } + else + { + mInvulnerable = false; + mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER; + } +} + +// Obtiene el valor de la variable +bool Player::hasExtraHit() +{ + return mExtraHit; +} + +// Concede un toque extra al jugador +void Player::giveExtraHit() +{ + mExtraHit = true; +} + +// Quita el toque extra al jugador +void Player::removeExtraHit() +{ + mExtraHit = false; + mInvulnerable = true; + mInvulnerableTimer = PLAYER_INVULNERABLE_TIMER; +} + +// Obtiene el circulo de colisión +Circle &Player::getCollider() +{ + return mCollider; +} + +// Actualiza el circulo de colisión a la posición del jugador +void Player::shiftColliders() +{ + mCollider.x = Uint16(mPosX + (mWidth / 2)); + mCollider.y = mPosY + (mHeight / 2); +} \ No newline at end of file diff --git a/source/player.h b/source/player.h new file mode 100644 index 0000000..0a9148c --- /dev/null +++ b/source/player.h @@ -0,0 +1,173 @@ +#pragma once +#include "struct.h" +#include "animatedsprite.h" + +#ifndef PLAYER_H +#define PLAYER_H + +// The player +class Player +{ +public: + // Constructor + Player(); + + // Destructor + ~Player(); + + // Iniciador + void init(float x, int y, LTexture *textureLegs, LTexture *textureBody, SDL_Renderer *renderer); + + // Actua en consecuencia de la entrada recibida + void setInput(Uint8 input); + + // Mueve el jugador a la posición y animación que le corresponde + void move(); + + // Pinta el jugador en pantalla + void render(); + + // Establece el estado del jugador + void setWalkingStatus(Uint8 status); + void setFiringStatus(Uint8 status); + + // Establece la animación correspondiente al estado + void setAnimation(); + + // Obtiene el valor de la variable + int getPosX(); + + // Obtiene el valor de la variable + int getPosY(); + + // Obtiene el valor de la variable + int getWidth(); + + // Obtiene el valor de la variable + int getHeight(); + + // Indica si el jugador puede disparar + bool canFire(); + + // Establece el valor de la variable + void setFireCooldown(int time); + + // Actualiza el valor de la variable + void updateCooldown(); + + // Actualiza al jugador a su posicion, animación y controla los contadores + void update(); + + // Obtiene la puntuación del jugador + int getScore(); + + // Asigna un valor a la puntuación del jugador + void setScore(int score); + + // Incrementa la puntuación del jugador + void addScore(int score); + + // Obtiene el valor de la variable + bool isAlive(); + + // Establece el valor de la variable + void setAlive(bool value); + + // Obtiene el valor de la variable + float getScoreMultiplier(); + + // Establece el valor de la variable + void setScoreMultiplier(float value); + + // Aumenta el valor de la variable hasta un máximo + void incScoreMultiplier(); + + // Decrementa el valor de la variable hasta un mínimo + void decScoreMultiplier(); + + // Obtiene el valor de la variable + bool isInvulnerable(); + + // Establece el valor de la variable + void setInvulnerable(bool value); + + // Obtiene el valor de la variable + bool getInvulnerableTimer(); + + // Establece el valor de la variable + void setInvulnerableTimer(Uint16 value); + + // Actualiza el valor de la variable + void updateInvulnerableTimer(); + + // Obtiene el valor de la variable + bool hasExtraHit(); + + // Concede un toque extra al jugador + void giveExtraHit(); + + // Quita el toque extra al jugador + void removeExtraHit(); + + // Obtiene el circulo de colisión + Circle &getCollider(); + +private: + // Posición X, Y del jugador + float mPosX; + int mPosY; + + // Altura y anchura del jugador + Uint8 mWidth; + Uint8 mHeight; + + // Velocidad X, Y del jugador + float mVelX; + int mVelY; + + // Velocidad base del jugador + float mBaseSpeed; + + // Contador durante el cual no puede disparar + int mCooldown; + + // Vidas actuales del jugador + Uint8 mLives; + + // Vidas iniciales del jugador + Uint8 mStartingLives; + + // Puntos del jugador + Uint32 mScore; + + // Multiplicador de puntos + float mScoreMultiplier; + + // Estado del jugador + Uint8 mStatusWalking; + Uint8 mStatusFiring; + + // Indica si el jugador está vivo + bool mAlive; + + // Indica si el jugador es invulnerable + bool mInvulnerable; + + // Temporizador para la invulnerabilidad + Uint16 mInvulnerableTimer; + + // Indica si el jugador tiene un toque extra + bool mExtraHit; + + // Sprite para dibujar al jugador en pantalla + AnimatedSprite *mSpriteLegs; + AnimatedSprite *mSpriteBody; + + // Circulo de colisión del jugador + Circle mCollider; + + // Actualiza el circulo de colisión a la posición del jugador + void shiftColliders(); +}; + +#endif diff --git a/source/smartsprite.cpp b/source/smartsprite.cpp new file mode 100644 index 0000000..5b68a17 --- /dev/null +++ b/source/smartsprite.cpp @@ -0,0 +1,228 @@ +#include "const.h" +#include "smartsprite.h" + +// Constructor +SmartSprite::SmartSprite() +{ + init(nullptr, nullptr); +} + +// Destructor +SmartSprite::~SmartSprite() +{ + init(nullptr, nullptr); +} + +// Inicializador +void SmartSprite::init(LTexture *texture, SDL_Renderer *renderer) +{ + setTexture(texture); + setRenderer(renderer); + + setPosX(0); + setPosY(0); + setWidth(0); + setHeight(0); + + setVelX(0); + setVelY(0); + setAccelX(0); + setAccelY(0); + + setSpriteClip(0, 0, 0, 0); + + setEnabled(false); + setEnabledTimer(0); + + mIsOnDestination = false; + mDestX = 0; + mDestY = 0; + + // El Id siempre es >=0, por lo tanto si no se le asigna Id se queda en negativo + mId = -1; + + mIntroEvents = nullptr; +} + +// Pone a cero los elementos del objeto +void SmartSprite::erase() +{ + init(nullptr, nullptr); +} + +// Obtiene el valor de la variable +bool SmartSprite::isEnabled() +{ + return mEnabled; +} + +// Establece el valor de la variable +void SmartSprite::setEnabled(bool state) +{ + mEnabled = state; +} + +// Obtiene el valor de la variable +Uint16 SmartSprite::getEnabledTimer() +{ + return mEnabledTimer; +} + +// Establece el valor de la variable +void SmartSprite::setEnabledTimer(Uint16 time) +{ + mEnabledTimer = time; +} + +// Establece el valor de la variable +void SmartSprite::setDestX(int value) +{ + mDestX = value; +} + +// Establece el valor de la variable +void SmartSprite::setDestY(int value) +{ + mDestY = value; +} + +// Obtiene el valor de la variable +int SmartSprite::getDestX() +{ + return mDestX; +} + +// Obtiene el valor de la variable +int SmartSprite::getDestY() +{ + return mDestY; +} + +// Actualiza la posición y comprueba si ha llegado a su destino +bool SmartSprite::update() +{ + if (mEnabled) + { + move(); + + // Comprueba si se desplaza en el eje X hacia la derecha + if ((getAccelX() > 0) || ((getAccelX() == 0) && (getVelX() > 0))) + { + // Comprueba si hemos llegado al destino + if (getPosX() > mDestX) + { + // Lo coloca en posición + setPosX(mDestX); + + // Lo detiene + setVelX(0.0f); + setAccelX(0.0f); + } + } + + // Comprueba si se desplaza en el eje X hacia la izquierda + else if ((getAccelX() < 0) || ((getAccelX() == 0) && (getVelX() < 0))) + { + // Comprueba si hemos llegado al destino + if (getPosX() < mDestX) + { + // Lo coloca en posición + setPosX(mDestX); + + // Lo detiene + setVelX(0.0f); + setAccelX(0.0f); + } + } + + // Comprueba si se desplaza en el eje Y hacia abajo + if ((getAccelY() > 0) || ((getAccelY() == 0) && (getVelY() > 0))) + { + // Comprueba si hemos llegado al destino + if (getPosY() > mDestY) + { + // Lo coloca en posición + setPosY(mDestY); + + // Lo detiene + setVelY(0.0f); + setAccelY(0.0f); + } + } + // Comprueba si se desplaza en el eje Y hacia arriba + else if ((getAccelY() < 0) || ((getAccelY() == 0) && (getVelY() < 0))) + { + // Comprueba si hemos llegado al destino + if (getPosY() < mDestY) + { + // Lo coloca en posición + setPosY(mDestY); + + // Lo detiene + setVelY(0.0f); + setAccelY(0.0f); + } + } + + // Comprueba si ha llegado a su destino + if ((getPosX() == mDestX) && (getPosY() == mDestY)) + { + mIsOnDestination = true; + } + else + { + mIsOnDestination = false; + } + + // Si esta en el destino comprueba su contador + if (mIsOnDestination) + { + // Si el contador es mayor que cero, lo decrementa + if (mEnabledTimer > 0) + { + --mEnabledTimer; + } + // Si ha llegado a cero, deshabilita el objeto o manda el aviso en función de si tiene Id + else if (mEnabledTimer == 0) + { + if (mId < 0) + { + mEnabled = false; + } + else + { + mIntroEvents[mId] = EVENT_COMPLETED; + } + } + } + } + + return mIsOnDestination; +} + +// Obtiene el valor de la variable +bool SmartSprite::isOnDestination() +{ + return mIsOnDestination; +} + +// Pinta el objeto en pantalla +void SmartSprite::render() +{ + if (mEnabled) + { + MovingSprite::render(); + } +} + +// Establece el valor de la variable +void SmartSprite::setId(int id) +{ + mId = id; +} + +// Establece el valor de la variable +void SmartSprite::setIntroEvents(Uint8 *value) +{ + mIntroEvents = value; +} \ No newline at end of file diff --git a/source/smartsprite.h b/source/smartsprite.h new file mode 100644 index 0000000..8061960 --- /dev/null +++ b/source/smartsprite.h @@ -0,0 +1,84 @@ +#pragma once +#include "struct.h" +#include "animatedsprite.h" + +#ifndef SMARTSPRITE_H +#define SMARTSPRITE_H + +// Clase SmartSprite +class SmartSprite : public AnimatedSprite +{ +public: + // Constructor + SmartSprite(); + + // Destructor + ~SmartSprite(); + + // Inicializador + void init(LTexture *texture, SDL_Renderer *renderer); + + // Pone a cero los elementos del objeto + void erase(); + + // Obtiene el valor de la variable + bool isEnabled(); + + // Establece el valor de la variable + void setEnabled(bool state); + + // Obtiene el valor de la variable + Uint16 getEnabledTimer(); + + // Establece el valor de la variable + void setEnabledTimer(Uint16 time); + + // Establece el valor de la variable + void setDestX(int value); + + // Establece el valor de la variable + void setDestY(int value); + + // Obtiene el valor de la variable + int getDestX(); + + // Obtiene el valor de la variable + int getDestY(); + + // Actualiza la posición y comprueba si ha llegado a su destino + bool update(); + + // Obtiene el valor de la variable + bool isOnDestination(); + + // Pinta el objeto en pantalla + void render(); + + // Establece el valor de la variable + void setId(int id); + + // Establece el valor de la variable + void setIntroEvents(Uint8 *value); + +private: + // Indica si esta habilitado + bool mEnabled; + + // Contador + Uint16 mEnabledTimer; + + // Indica si está en el destino + bool mIsOnDestination; + + // Posicion de destino + int mDestX; + int mDestY; + + // Identificador + int mId; + + // Dirección del array de eventos donde notificar el estado + Uint8 *mIntroEvents; +}; + +#endif diff --git a/source/sprite.cpp b/source/sprite.cpp new file mode 100644 index 0000000..23df471 --- /dev/null +++ b/source/sprite.cpp @@ -0,0 +1,149 @@ +#include "sprite.h" + +// Constructor +Sprite::Sprite() +{ + init(0, 0, 0, 0, nullptr, nullptr); +} + +// Destructor +Sprite::~Sprite() +{ + mTexture = nullptr; + mRenderer = nullptr; +} + +// Inicializador +void Sprite::init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer) +{ + // Establece el alto y el ancho del sprite + setWidth(w); + setHeight(h); + + // Establece la posición X,Y del sprite + setPosX(x); + setPosY(y); + + // Establece el puntero al renderizador de la ventana + setRenderer(renderer); + + // Establece la textura donde están los gráficos para el sprite + setTexture(texture); + + // Establece el rectangulo de donde coger la imagen + setSpriteClip(0, 0, w, h); +} + +// Inicializador +void Sprite::init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer) +{ + // Establece el alto y el ancho del sprite + mWidth = rect.w; + mHeight = rect.h; + + // Establece la posición X,Y del sprite + mPosX = rect.x; + mPosY = rect.y; + + // Establece el puntero al renderizador de la ventana + setRenderer(renderer); + + // Establece la textura donde están los gráficos para el sprite + setTexture(texture); + + // Establece el rectangulo de donde coger la imagen + setSpriteClip(rect); +} + +// Muestra el sprite por pantalla +void Sprite::render() +{ + mTexture->render(mRenderer, mPosX, mPosY, &mSpriteClip); +} + +// Obten el valor de la variable +int Sprite::getPosX() +{ + return mPosX; +} + +// Obten el valor de la variable +int Sprite::getPosY() +{ + return mPosY; +} + +// Obten el valor de la variable +int Sprite::getWidth() +{ + return mWidth; +} + +// Obten el valor de la variable +int Sprite::getHeight() +{ + return mHeight; +} + +// Establece el valor de la variable +void Sprite::setPosX(int x) +{ + mPosX = x; +} + +// Establece el valor de la variable +void Sprite::setPosY(int y) +{ + mPosY = y; +} + +// Establece el valor de la variable +void Sprite::setWidth(int w) +{ + mWidth = w; +} + +// Establece el valor de la variable +void Sprite::setHeight(int h) +{ + mHeight = h; +} + +// Obten el valor de la variable +SDL_Rect Sprite::getSpriteClip() +{ + return mSpriteClip; +} + +// Establece el valor de la variable +void Sprite::setSpriteClip(SDL_Rect rect) +{ + mSpriteClip = rect; +} + +// Establece el valor de la variable +void Sprite::setSpriteClip(int x, int y, int w, int h) +{ + mSpriteClip.x = x; + mSpriteClip.y = y; + mSpriteClip.w = w; + mSpriteClip.h = h; +} + +// Obten el valor de la variable +LTexture *Sprite::getTexture() +{ + return mTexture; +} + +// Establece el valor de la variable +void Sprite::setTexture(LTexture *texture) +{ + mTexture = texture; +} + +// Establece el valor de la variable +void Sprite::setRenderer(SDL_Renderer *renderer) +{ + mRenderer = renderer; +} \ No newline at end of file diff --git a/source/sprite.h b/source/sprite.h new file mode 100644 index 0000000..9654ed8 --- /dev/null +++ b/source/sprite.h @@ -0,0 +1,87 @@ +#pragma once +#include "ifdefs.h" +#include "ltexture.h" + +#ifndef SPRITE_H +#define SPRITE_H + +// Clase sprite +class Sprite +{ +public: + // Constructor + Sprite(); + + // Destructor + ~Sprite(); + + // Inicializador + void init(int x, int y, int w, int h, LTexture *texture, SDL_Renderer *renderer); + void init(SDL_Rect rect, LTexture *texture, SDL_Renderer *renderer); + + // Muestra el sprite por pantalla + void render(); + + // Obten el valor de la variable + int getPosX(); + + // Obten el valor de la variable + int getPosY(); + + // Obten el valor de la variable + int getWidth(); + + // Obten el valor de la variable + int getHeight(); + + // Establece el valor de la variable + void setPosX(int x); + + // Establece el valor de la variable + void setPosY(int y); + + // Establece el valor de la variable + void setWidth(int w); + + // Establece el valor de la variable + void setHeight(int h); + + // Obten el valor de la variable + SDL_Rect getSpriteClip(); + + // Establece el valor de la variable + void setSpriteClip(SDL_Rect rect); + + // Establece el valor de la variable + void setSpriteClip(int x, int y, int w, int h); + + // Obten el valor de la variable + LTexture* getTexture(); + + // Establece el valor de la variable + void setTexture(LTexture *texture); + + // Establece el valor de la variable + void setRenderer(SDL_Renderer *renderer); + + +protected: + // Posición X,Y donde dibujar el sprite + int mPosX; + int mPosY; + + // Alto y ancho del sprite + Uint16 mWidth; + Uint16 mHeight; + + // Puntero al renderizador de la ventana + SDL_Renderer *mRenderer; + + // Textura donde estan todos los dibujos del sprite + LTexture *mTexture; + + // Rectangulo de la textura que se dibujará en pantalla + SDL_Rect mSpriteClip; +}; + +#endif diff --git a/source/text.cpp b/source/text.cpp new file mode 100644 index 0000000..b4b8cce --- /dev/null +++ b/source/text.cpp @@ -0,0 +1,244 @@ +#include "const.h" +#include "text.h" + +// Constructor +Text::Text() +{ + mSprite = new Sprite(); + init(nullptr, nullptr, 0, 0); +} + +// Destructor +Text::~Text() +{ + delete mSprite; +} + +// Inicializador +void Text::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size) +{ + // Inicializa variables + mType = type; + mSize = size; + + // Inicia los valores del sprite que dibuja las letras + mSprite->setWidth(size); + mSprite->setHeight(size); + mSprite->setPosX(0); + mSprite->setPosY(0); + mSprite->setTexture(texture); + mSprite->setRenderer(renderer); + mSprite->setSpriteClip(0, 0, mSprite->getWidth(), mSprite->getHeight()); + + // Cadena con los caracteres ascii que se van a inicializar + // std::string text = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-/().:#!"; + std::string text = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ{\\[]]^_`abcdefghijklmnopqrstuvwxyz"; + + // Inicializa a cero el vector con las coordenadas + for (Uint8 i = 0; i < 255; i++) + { + mOffset[i].x = 0; + mOffset[i].y = 0; + mOffset[i].w = 0; + } + + // Establece las coordenadas para cada caracter ascii de la cadena y su ancho + for (Uint8 i = 0; i < text.length(); ++i) + { + mOffset[int(text[i])].x = ((int(text[i]) - 32) % 15) * mSprite->getWidth(); + mOffset[int(text[i])].y = ((int(text[i]) - 32) / 15) * mSprite->getHeight(); + if (type == TEXT_FIXED) + { + mOffset[int(text[i])].w = size; + } + } + + // Establece el ancho de cada caracter + if (type == TEXT_VARIABLE) + { + mOffset[int(' ')].w = 7; + mOffset[int('-')].w = 6; + mOffset[int('/')].w = 5; + mOffset[int('(')].w = 5; + mOffset[int(')')].w = 5; + mOffset[int('.')].w = 4; + mOffset[int(':')].w = 4; + mOffset[int('#')].w = 7; + mOffset[int('!')].w = 7; + mOffset[int('\'')].w = 3; + + mOffset[int('0')].w = 7; + mOffset[int('1')].w = 5; + mOffset[int('2')].w = 7; + mOffset[int('3')].w = 7; + mOffset[int('4')].w = 7; + mOffset[int('5')].w = 7; + mOffset[int('6')].w = 7; + mOffset[int('7')].w = 7; + mOffset[int('8')].w = 7; + mOffset[int('9')].w = 7; + + mOffset[int('A')].w = 7; + mOffset[int('B')].w = 7; + mOffset[int('C')].w = 7; + mOffset[int('D')].w = 7; + mOffset[int('E')].w = 7; + mOffset[int('F')].w = 7; + mOffset[int('G')].w = 7; + mOffset[int('H')].w = 7; + mOffset[int('I')].w = 4; + mOffset[int('J')].w = 6; + mOffset[int('K')].w = 8; + mOffset[int('L')].w = 6; + mOffset[int('M')].w = 9; + mOffset[int('N')].w = 8; + mOffset[int('O')].w = 8; + mOffset[int('P')].w = 7; + mOffset[int('Q')].w = 8; + mOffset[int('R')].w = 7; + mOffset[int('S')].w = 6; + mOffset[int('T')].w = 8; + mOffset[int('U')].w = 7; + mOffset[int('V')].w = 8; + mOffset[int('W')].w = 9; + mOffset[int('X')].w = 8; + mOffset[int('Y')].w = 8; + mOffset[int('Z')].w = 7; + + mOffset[int('a')].w = 7; + mOffset[int('b')].w = 7; + mOffset[int('c')].w = 6; + mOffset[int('d')].w = 7; + mOffset[int('e')].w = 7; + mOffset[int('f')].w = 5; + mOffset[int('g')].w = 7; + mOffset[int('h')].w = 7; + mOffset[int('i')].w = 4; + mOffset[int('j')].w = 5; + mOffset[int('k')].w = 7; + mOffset[int('l')].w = 4; + mOffset[int('m')].w = 10; + mOffset[int('n')].w = 7; + mOffset[int('o')].w = 7; + mOffset[int('p')].w = 7; + mOffset[int('q')].w = 7; + mOffset[int('r')].w = 6; + mOffset[int('s')].w = 6; + mOffset[int('t')].w = 5; + mOffset[int('u')].w = 7; + mOffset[int('v')].w = 7; + mOffset[int('w')].w = 9; + mOffset[int('x')].w = 7; + mOffset[int('y')].w = 7; + mOffset[int('z')].w = 7; + } +} + +// Escribe el texto en pantalla +void Text::write(int x, int y, std::string text) +{ + Uint16 shift = 0; + for (Uint8 i = 0; i < text.length(); ++i) + { + mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); + mSprite->setPosX(x + shift); + mSprite->setPosY(y); + mSprite->render(); + shift += (mOffset[int(text[i])].w); + } +} + +// Escribe el texto en pantalla con kerning +void Text::write(int x, int y, std::string text, int kerning) +{ + Uint16 shift = 0; + for (Uint8 i = 0; i < text.length(); ++i) + { + mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); + mSprite->setPosX(x + shift); + mSprite->setPosY(y); + mSprite->render(); + shift += (mOffset[int(text[i])].w + kerning); + } +} + +// Escribe una cantidad determinada de caracteres del texto en pantalla +void Text::write(int x, int y, std::string text, int kerning, Uint8 lenght) +{ + Uint16 shift = 0; + for (Uint8 i = 0; i < lenght; ++i) + { + if (text[i] == '*') + { + shift = 0; + y += mSize; + } + else + { + mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); + mSprite->setPosX(x + shift); + mSprite->setPosY(y); + mSprite->render(); + shift += (mOffset[int(text[i])].w + kerning); + } + } +} + +// Escribe el texto con colores +void Text::writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B) +{ + mSprite->getTexture()->setColor(R, G, B); + write(x, y, text); + mSprite->getTexture()->setColor(255, 255, 255); +} + +// Escribe el texto centrado en un punto x y con kerning +void Text::writeCentered(int x, int y, std::string text, int kerning) +{ + // Uint16 lenght = Text::lenght(text, kerning); + x = x - (Text::lenght(text, kerning) / 2); + Uint16 shift = 0; + for (Uint8 i = 0; i < text.length(); ++i) + { + mSprite->setSpriteClip(mOffset[int(text[i])].x, mOffset[int(text[i])].y, mSprite->getWidth(), mSprite->getHeight()); + mSprite->setPosX(x + shift); + mSprite->setPosY(y); + mSprite->render(); + shift += (mOffset[int(text[i])].w + kerning); + } +} + +// Obtiene la longitud en pixels de una cadena +Uint16 Text::lenght(std::string text, int kerning) +{ + Uint16 shift = 0; + for (Uint8 i = 0; i < text.length(); ++i) + { + shift += (mOffset[int(text[i])].w + kerning); + } + return shift; +} + +// Obtiene el valor de la variable +Uint8 Text::getType() +{ + return mType; +} + +// Establece el valor de la variable +void Text::setType(Uint8 type) +{ + mType = type; +} + +// Obtiene el valor de la variable +Uint8 Text::getSize() +{ + return mSize; +} + +// Establece el valor de la variable +void Text::setSize(Uint8 size) +{ + mSize = size; +} \ No newline at end of file diff --git a/source/text.h b/source/text.h new file mode 100644 index 0000000..f651c59 --- /dev/null +++ b/source/text.h @@ -0,0 +1,66 @@ +#pragma once +#include "sprite.h" + +#ifndef TEXT_H +#define TEXT_H + +// Clase texto. Pinta texto en pantalla a partir de un bitmap +class Text +{ +public: + // Constructor + Text(); + + // Destructor + ~Text(); + + // Inicializador + void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size); + + // Escribe el texto en pantalla + void write(int x, int y, std::string text); + void write(int x, int y, std::string text, int kerning); + void write(int x, int y, std::string text, int kerning, Uint8 lenght); + + // Escribe el texto con colores + void writeColored(int x, int y, std::string text, Uint8 R, Uint8 G, Uint8 B); + + // Escribe el texto centrado en un punto x y con kerning + void writeCentered(int x, int y, std::string text, int kerning); + + // Obtiene la longitud en pixels de una cadena + Uint16 lenght(std::string text, int kerning); + + // Obtiene el valor de la variable + Uint8 getType(); + + // Establece el valor de la variable + void setType(Uint8 type); + + // Obtiene el valor de la variable + Uint8 getSize(); + + // Establece el valor de la variable + void setSize(Uint8 size); + +private: + // Objeto con los graficos para el texto + Sprite *mSprite; + + // Coordenadas dentro del PNG para cada código ascii y su anchura + struct Offset + { + int x; + int y; + Uint8 w; + }; + + // Vector con las posiciones y ancho de cada letra + Offset mOffset[255]; + + // Indica si el texto es de anchura fija o variable + Uint8 mType; + Uint8 mSize; +}; + +#endif diff --git a/source/text2.cpp b/source/text2.cpp new file mode 100644 index 0000000..6b9586c --- /dev/null +++ b/source/text2.cpp @@ -0,0 +1,158 @@ +#include "const.h" +#include "text2.h" + +// Constructor +Text2::Text2() +{ + init(nullptr, nullptr, 0, 0); +} + +// Destructor +Text2::~Text2() +{ + init(nullptr, nullptr, 0, 0); +} + +// Inicializador +void Text2::init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size) +{ + Text::init(texture, renderer, type, size); + mPosX = 0; + mPosY = 0; + mKerning = 0; + mCaption = ""; + mWrittingSpeed = 0; + mWrittingTimer = 0; + mIndex = 0; + mLenght = 0; + mWrittingCompleted = false; + mEnabled = false; + mEnabledTimer = 0; + mId = -1; + mIntroEvents = nullptr; +} + +// Establece el valor de la variable +void Text2::setPosX(int value) +{ + mPosX = value; +} + +// Establece el valor de la variable +void Text2::setPosY(int value) +{ + mPosY = value; +} + +// Establece el valor de la variable +void Text2::setKerning(int value) +{ + mKerning = value; +} + +// Establece el valor de la variable +void Text2::setCaption(std::string text) +{ + mCaption = text; + mLenght = text.length(); +} + +// Establece el valor de la variable +void Text2::setWrittingSpeed(Uint16 value) +{ + mWrittingSpeed = value; + mWrittingTimer = value; +} + +// Establece el valor de la variable +void Text2::setEnabled(bool value) +{ + mEnabled = value; +} + +// Obtiene el valor de la variable +bool Text2::IsEnabled() +{ + return mEnabled; +} + +// Establece el valor de la variable +void Text2::setEnabledTimer(Uint16 value) +{ + mEnabledTimer = value; +} + +// Obtiene el valor de la variable +Uint16 Text2::getEnabledTimer() +{ + return mEnabledTimer; +} + +// Actualiza el objeto +void Text2::update() +{ + if (mEnabled) + { + if (mWrittingCompleted == false) + { + if (mWrittingTimer > 0) + { + --mWrittingTimer; + } + if (mWrittingTimer == 0) + { + ++mIndex; + mWrittingTimer = mWrittingSpeed; + } + if (mIndex == mLenght) + { + mWrittingCompleted = true; + } + } + if (mWrittingCompleted) + { + if (mEnabledTimer > 0) + { + --mEnabledTimer; + } + else if (mEnabledTimer == 0) + { + if (mId < 0) + { + mEnabled = false; + } + else + { + mIntroEvents[mId] = EVENT_COMPLETED; + } + } + } + } +} + +// Dibuja el objeto en pantalla +void Text2::render() +{ + if (mEnabled) + { + Text::write(mPosX, mPosY, mCaption, mKerning, mIndex); + } +} + +// Centra la cadena de texto a un punto X +void Text2::center(int x) +{ + setPosX(x - (lenght(mCaption, mKerning) / 2)); +} + +// Establece el valor de la variable +void Text2::setId(int id) +{ + mId = id; +} + +// Establece el valor de la variable +void Text2::setIntroEvents(Uint8 *value) +{ + mIntroEvents = value; +} diff --git a/source/text2.h b/source/text2.h new file mode 100644 index 0000000..9366d61 --- /dev/null +++ b/source/text2.h @@ -0,0 +1,102 @@ +#pragma once +#include "sprite.h" +#include "text.h" + +#ifndef TEXT2_H +#define TEXT2_H + +// Clase texto. Pinta texto en pantalla a partir de un bitmap +class Text2 : public Text +{ +public: + // Constructor + Text2(); + + // Destructor + ~Text2(); + + // Inicializador + void init(LTexture *texture, SDL_Renderer *renderer, Uint8 type, Uint8 size); + + // Establece el valor de la variable + void setPosX(int value); + + // Establece el valor de la variable + void setPosY(int value); + + // Establece el valor de la variable + void setKerning(int value); + + // Establece el valor de la variable + void setCaption(std::string text); + + // Establece el valor de la variable + void setWrittingSpeed(Uint16 value); + + // Establece el valor de la variable + void setEnabled(bool value); + + // Obtiene el valor de la variable + bool IsEnabled(); + + // Establece el valor de la variable + void setEnabledTimer(Uint16 value); + + // Obtiene el valor de la variable + Uint16 getEnabledTimer(); + + // Actualiza el objeto + void update(); + + // Dibuja el objeto en pantalla + void render(); + + // Centra la cadena de texto a un punto X + void center(int x); + + // Establece el valor de la variable + void setId(int id); + + // Establece el valor de la variable + void setIntroEvents(Uint8 *value); + +private: + // Posicion X/Y donde empezar a escribir el texto + int mPosX; + int mPosY; + + // Kerning del texto + int mKerning; + + // Texto para escribir + std::string mCaption; + + // Velocidad de escritura + Uint16 mWrittingSpeed; + + // Temporizador de escritura para cada caracter + Uint16 mWrittingTimer; + + // Posición del texto que se está escribiendo + Uint16 mIndex; + + // Longitud de la cadena a escribir + Uint16 mLenght; + + // Indica si se ha escrito todo el texto + bool mWrittingCompleted; + + // Indica si el objeto está habilitado + bool mEnabled; + + // Temporizador para deshabilitar el objeto + Uint16 mEnabledTimer; + + // Identificador + int mId; + + // Dirección del array de eventos donde notificar el estado + Uint8 *mIntroEvents; +}; + +#endif diff --git a/source/volcano.pas b/source/volcano.pas deleted file mode 100644 index fff7345..0000000 --- a/source/volcano.pas +++ /dev/null @@ -1,2704 +0,0 @@ -program Volcano; -{$IFDEF DARWIN} - {$linkframework Cocoa} - {$linkframework SDL2} - {$linkframework OpenGL} - {$linkframework SDL2_image} - {$linkframework SDL2_mixer} -{$ELSE} - {$APPTYPE GUI} -{$ENDIF} - - -// Volcano (abans "Rise of the Bal1") -// Programat i dissenyat per Sergio Valor @JailDesigner -// Editor, música i suport técnic per Raimon Zamora @JailDoc -// Gràfics per Diego Valor @JailBrother -// Començat un 19 de febrer de 2016 - -uses sdl2, SDL2_image, SDL2_mixer; - -const - GAME_SPEED = 24; //16 = normal-rapid, 24 = normal. Quan menor, més ràpid - - UP = 0; - DOWN = 2; - RIGHT = 1; - LEFT = 3; - NONE = 4; - - MAP_TILE_HEIGHT = 16; - MAP_TILE_WIDTH = 16; - - ROOM_WIDTH_IN_TILES = 20; - ROOM_HEIGHT_IN_TILES = 14; - - GAME_WINDOW_WIDTH = 320; - GAME_WINDOW_HEIGHT = 234; - - TEST_ROOM = 118; - STARTING_ROOM = 161;//TEST_ROOM; - STARTING_PLAYER_TILE_X = 5; - STARTING_PLAYER_TILE_Y = 11; - ENEMY_HITBOX_REDUCTION = 4; - COOLDOWN_TIME = 50; - GRAVITY = 1; - MAX_SPEED_Y = 5; - BASE_SPEED = 1; - MAX_SPEED = 8; - RATIO_SPEED = 8; - DROP_TIMER = 100; - - TOP_COLLISION = 0; - BOTTOM_COLLISION = 1; - LEFT_COLLISION = 2; - RIGHT_COLLISION = 3; - NO_COLLISION = 4; - - MAX_ACTORS = 50; - - KIND_FLYING_ENEMY = 0; - KIND_COIN = 1; - KIND_HEART = 2; - KIND_STATIC_ENEMY = 3; - KIND_MOBILE_PLATFORM = 4; - KIND_WALKING_ENEMY = 5; - KIND_DROP_GENERATOR = 6; - KIND_DROP_ENEMY = 7; - KIND_DROP_SPLAT = 8; - KIND_SPEED_ENEMY = 9; - KIND_KEY = 10; - KIND_LOCK = 11; - - CODE_ENEMY_V1U = 208; - CODE_ENEMY_V2U = 209; - CODE_ENEMY_V3U = 210; - CODE_ENEMY_V1D = 211; - CODE_ENEMY_V2D = 212; - CODE_ENEMY_V3D = 213; - - CODE_ENEMY_H1L = 214; - CODE_ENEMY_H2L = 215; - CODE_ENEMY_H3L = 216; - CODE_ENEMY_H1R = 217; - CODE_ENEMY_H2R = 218; - CODE_ENEMY_H3R = 219; - - CODE_ENEMY_W1L = 224; - CODE_ENEMY_W2L = 225; - CODE_ENEMY_W3L = 226; - CODE_ENEMY_W1R = 227; - CODE_ENEMY_W2R = 228; - CODE_ENEMY_W3R = 229; - - CODE_ENEMY_DRP = 230; - - CODE_ENEMY_SPL = 231; - CODE_ENEMY_SPR = 232; - - CODE_COIN = 240; - CODE_HEART = 241; - CODE_KEY_RED = 242; - CODE_LOCK_RED = 243; - CODE_KEY_BLUE = 244; - CODE_LOCK_BLUE = 245; - CODE_KEY_GREEN = 246; - CODE_LOCK_GREEN = 247; - CODE_KEY_YELLOW = 248; - CODE_LOCK_YELLOW = 249; - - MAX_ANIMATED_TILES = 200; - - TILE_BACKGROUND = 0; - TILE_PLATFORM = 1; - TILE_KILLING_PLATFORM = 2; - TILE_ACTOR = 3; - TILE_TRAVESABLE_PLATFORM = 4; - - PLAYER_ANIMATION_STANDING_LEFT = 0; - PLAYER_ANIMATION_STANDING_RIGHT = 1; - PLAYER_ANIMATION_WALKING_LEFT = 2; - PLAYER_ANIMATION_WALKING_RIGHT = 3; - PLAYER_ANIMATION_JUMPING_LEFT = 4; - PLAYER_ANIMATION_JUMPING_RIGHT = 5; - PLAYER_ANIMATION_DYING_LEFT = 6; - PLAYER_ANIMATION_DYING_RIGHT = 7; - - SECTION_MENU = 0; - SECTION_GAME = 1; - SECTION_QUIT = 2; - - MENU_SECTION_MAIN = 0; - MENU_SECTION_CREDITS = 1; - MENU_SECTION_ANIMATION = 2; - - ZONE_SURFACE = 0; - ZONE_VOLCANO = 1; - - WINDOW_TITLE = 'Volcano v0005'; - BUILD = '.05'; - FILE_MAP_VOLCANO = './data/volcano.map'; - FILE_TILES_VOLCANO = './data/gfx/tiles_volcano.png'; - FILE_TILES_SURFACE = './data/gfx/tiles_surface.png'; - FILE_BKG_SURFACE = './data/gfx/bkg_surface.png'; - FILE_MENU = './data/gfx/menu.png'; - FILE_MENU_ANIMATION = './data/gfx/menu_animation.png'; - FILE_ACTORS = './data/gfx/actors.png'; - FILE_PLAYER = './data/gfx/player.png'; - FILE_HUD = './data/gfx/hud.png'; - FILE_FILTER = './data/gfx/filter.png'; - FILE_SOUND_JUMP = './data/sound/sound_player_jump.wav'; - FILE_SOUND_DEATH = './data/sound/sound_player_death.wav'; - FILE_SOUND_COIN = './data/sound/sound_player_coin.wav'; - FILE_SOUND_MENU_LOGO = './data/sound/sound_menu_logo.wav'; - FILE_SOUND_MENU_START = './data/sound/sound_menu_start.wav'; - FILE_SOUND_DROP_ENEMY = './data/sound/sound_drop_enemy.wav'; - FILE_SOUND_DROP_SPLAT = './data/sound/sound_drop_splat.wav'; - FILE_MUSIC_SURFACE = './data/music/music_surface.mp3'; - FILE_MUSIC_VOLCANO = './data/music/music_volcano.mp3'; - FILE_MUSIC_MENU = './data/music/music_menu.mp3'; - -type - Tanimation = record - num_frames: byte; - index: byte; - speed: byte; - timer: longword; - loops: boolean; // salta a TRUE quan la animació es reinicia - frame: array [0 .. 49] of byte; - end; - - Tprogram = record - music_enabled: boolean; - filter: boolean; - section: byte; - debug: boolean; - sprite: PSDL_Texture; - src_rect: TSDL_Rect; - dst_rect: TSDL_Rect; - end; - - Tgame = record - zone: byte; // Zona en la que estem - music: PMix_Music; - enabled: boolean; - sound_drop_enemy: PMix_Chunk; - sound_drop_splat: PMix_Chunk; - end; - - Tmenu = record - section: byte; - sprite: PSDL_Texture; - sprite_animation: PSDL_Texture; - src_rect_fondo: TSDL_Rect; - dst_rect_fondo: TSDL_Rect; - src_rect_logo: TSDL_Rect; - dst_rect_logo: TSDL_Rect; - dst_rect_logo_zoom: TSDL_Rect; - src_rect_text: TSDL_Rect; - dst_rect_text: TSDL_Rect; - src_rect_text2: TSDL_Rect; - dst_rect_text2: TSDL_Rect; - music: PMix_Music; - sound_logo: PMix_Chunk; - sound_start: PMix_Chunk; - frame: integer; - enabled: boolean; - timer: integer; - animation: array [0..1] of Tanimation; - src_rect_animation: TSDL_Rect; - dst_rect_animation: TSDL_Rect; - end; - - Tplayer = record - sprite: PSDL_Texture; - src_rect: TSDL_Rect; - dst_rect: TSDL_Rect; - direction: byte; // Sentit del desplaçament - speed_x, - speed_y: integer; // Quantitat de pixels a desplaçar - jumpforce: integer; // Quantitat de pixels a desplaçar i velocitat que pilla al saltar - active_animation: byte; // Index per al array d'animació - animation: array [0 .. 7] of Tanimation; - can_jump: boolean; // Indica si el jugador pot saltar (FALSE si ja està saltant) - jump_pressed_now, - jump_pressed_before: boolean; // Indica si el botó de saltar està apretat, per evitar el autofire - standing: boolean; // Indica si el jugador está quet. - respawn_x, - respawn_y: integer; // Coordenades per a reviure - respawn_direction: byte; // Per a reviure en la mateixa direcció que s'entra a la habitació - enabled: boolean; // Indica si pot rebre ordres - cooldown: integer; // Temps d'inhabilitació - lifes: byte; // Quantitat de vides - coins: integer; // Quantitat de monedes - key: array [0..5] of boolean; - sound_jump: PMix_Chunk; - sound_death: PMix_Chunk; - sound_coin: PMix_Chunk; - was_on_background: boolean; // Ens guardem si en l'anterior loop el tile sobre el qual teniem els nostres peus era background [27/05/2016] [DOC] - end; - - Tactor = record - src_rect: TSDL_Rect; - dst_rect: TSDL_Rect; - //animation: Tanimation; - kind: byte; // Tipus d'actor: enemic, moneda, clau, plataforma ... - direction: byte; // Sentit del desplaçament - id: byte; - speed_x, - speed_y: integer; // Velocitat = quantitat de pixels a desplaçar - frame: integer; - timer: integer; - enabled: boolean; - parent: byte; // Index al pare de l'actor - end; - - Tanimated_tile = record - enabled: boolean; - x, y: integer; - index: integer; - frame: byte; - end; - - Thud = record - sprite: PSDL_Texture; - src_rect: TSDL_Rect; - dst_rect: TSDL_Rect; - num_src_rect: TSDL_Rect; - num_dst_rect: TSDL_Rect; - bignum_src_rect: TSDL_Rect; - bignum_dst_rect: TSDL_Rect; - end; - - Pmap = ^Tmap; - Tmap = record - sprite_tile: PSDL_Texture; - sprite_actor: PSDL_Texture; - background: PSDL_Texture; - src_rect: TSDL_Rect; - dst_rect: TSDL_Rect; - tile: array of byte; - actor: array of byte; - w, h: byte; - room: byte; - end; - -var - fullscreen: boolean; - window: PSDL_Window; - renderer: PSDL_Renderer; - prog: Tprogram; - menu: Tmenu; - game: Tgame; - player: Tplayer; - map: Tmap; - hud: Thud; - actor: array [0..MAX_ACTORS - 1] of Tactor; - animated_tile: array [0..MAX_ANIMATED_TILES - 1] of Tanimated_tile; - e: TSDL_Event; - keys: PUInt8; - quit: boolean; - delta_time: Uint32; - i: byte; - -function max(a,b:integer):integer; -begin - if a > b then max:=a else max:=b; -end; - -function min(a,b:integer):integer; -begin - if a < b then min:=a else min:=b; -end; - -function OpenPicture(name: PChar) : PSDL_Texture; -var - image: PSDL_Surface; - texture: PSDL_Texture; -begin - image := IMG_Load(name); - texture := SDL_CreateTextureFromSurface(renderer, image); - SDL_FreeSurface(image); - OpenPicture := texture; -end; - -procedure CloseSound(var sound: PMix_Chunk); -begin - if sound <> nil then - Mix_FreeChunk(sound); - sound := nil; -end; - -procedure CloseMusic(var music: PMix_Music); -begin - if music <> nil then - Mix_FreeMusic(music); - music := nil; -end; - -procedure ClosePicture(var picture: PSDL_Texture); -begin - if picture <> nil then - SDL_DestroyTexture(picture); - picture := nil; -end; - -function GetTile(x, y: byte): byte; -// Entrada: coordenades en tiles relatives a la habitació actual -// Eixida: el valor del byte -var - room_x, room_y: byte; -begin - room_x := (map.room mod 12) * ROOM_WIDTH_IN_TILES; - room_y := (map.room div 12) * ROOM_HEIGHT_IN_TILES; - GetTile := map.tile[(room_x + x ) + (room_y + y) * map.w]; -end; - -function ReadMapTile(x, y: byte): byte; -begin - case GetTile(x,y) of - 000 .. 063: ReadMapTile := TILE_BACKGROUND; - 064 .. 143: ReadMapTile := TILE_PLATFORM; - 144 .. 175: ReadMapTile := TILE_TRAVESABLE_PLATFORM; - 176 .. 207: ReadMapTile := TILE_KILLING_PLATFORM; - 208 .. 255: ReadMapTile := TILE_ACTOR; - else ReadMapTile := TILE_BACKGROUND; - end; -end; - -function GetActor(x, y: byte): byte; -var - room_x, room_y : byte; -begin - room_x := (map.room mod 12) * ROOM_WIDTH_IN_TILES; - room_y := (map.room div 12) * ROOM_HEIGHT_IN_TILES; - GetActor := map.actor[(room_x + x) + (room_y + y) * map.w]; -end; - -Procedure SetActor(x, y, valor: byte); -var - room_x, room_y : byte; -begin - room_x := (map.room mod 12) * ROOM_WIDTH_IN_TILES; - room_y := (map.room div 12) * ROOM_HEIGHT_IN_TILES; - map.actor[(room_x + x) + (room_y + y) * map.w] := valor; -end; - -procedure SetMapGFX(zone: byte); -begin - case zone of - ZONE_SURFACE: - begin - map.sprite_tile := OpenPicture(FILE_TILES_SURFACE); - map.background := OpenPicture(FILE_BKG_SURFACE); - end; - - ZONE_VOLCANO: - begin - map.sprite_tile := OpenPicture(FILE_TILES_VOLCANO); - map.background := OpenPicture(FILE_BKG_SURFACE); - end; - end; -end; - -procedure SetMapMusic(zone: byte); -begin - case zone of - ZONE_SURFACE: - game.music := Mix_LoadMUS(FILE_MUSIC_SURFACE); - - ZONE_VOLCANO: - game.music := Mix_LoadMUS(FILE_MUSIC_VOLCANO); - end; -end; - -function CheckZoneChange(room: integer): boolean; -var - zone: byte; -begin - case room of - 0 .. 23: - zone := ZONE_SURFACE; - 24 .. 255: - zone := ZONE_VOLCANO; - end; - - if (zone = game.zone) then - CheckZoneChange := FALSE - else - CheckZoneChange := TRUE; -end; - -procedure SetZone(room: integer); -begin - case room of - 0 .. 23: - game.zone := ZONE_SURFACE; - - 24 .. 255: - game.zone := ZONE_VOLCANO; - end; - - SetMapGFX(game.zone); - SetMapMusic(game.zone); - Mix_PlayMusic(game.music, -1); -end; - -procedure SetPlayerAnimation(anim: byte); -begin - if (anim <> player.active_animation) then - begin - player.active_animation := anim; - player.src_rect.y := anim * player.src_rect.h; - player.animation[anim].index := 0; - player.animation[anim].timer := 0; - player.animation[anim].loops := FALSE; - end; -end; - -procedure Animate(var a:Tanimation; var s:TSDL_Rect); -begin - // Mirem si estem en el penultim frame per avisar de que anem a pintar el ultim - if (a.timer = (a.num_frames * a.speed) - 2) then - a.loops := TRUE - else - a.loops := FALSE; - - a.timer := (a.timer + 1) mod (a.num_frames * a.speed); - a.index := a.timer div a.speed; - s.x := (a.frame[a.index]) * s.w; -end; - -procedure AnimateIntroMenu(var a:Tanimation; var s:TSDL_Rect); -begin - // Mirem si estem en el penultim frame per avisar de que anem a pintar el ultim - if (a.timer = (a.num_frames * a.speed) - 2) then - a.loops := TRUE - else - a.loops := FALSE; - - a.timer := (a.timer + 1) mod (a.num_frames * a.speed); - a.index := a.timer div a.speed; - s.x := (a.frame[a.index] mod 4) * s.w; - s.y := (a.frame[a.index] div 4) * s.h; -end; - -procedure CreateActor(var a : Tactor; kind, id : byte; dstx, dsty, dstw, dsth, srcx, srcy, sx, sy, timer, frame : smallint; direction, parent : byte); -begin - a.kind := kind; - a.id := id; - a.dst_rect.x := dstx; - a.dst_rect.y := dsty; - a.dst_rect.w := dstw; - a.dst_rect.h := dsth; - a.src_rect.x := srcx; - a.src_rect.y := srcy; - a.src_rect.w := a.dst_rect.w; - a.src_rect.h := a.dst_rect.h; - a.direction := direction; - a.speed_x := sx; - a.speed_y := sy; - a.timer := timer; - a.frame := frame; - a.enabled := TRUE; - a.parent := parent; -end; - -procedure LoadMap(map:Pmap); -var - f: File; - numread: Word; - size: array[0..1] of byte; -begin - Assign(f, FILE_MAP_VOLCANO); - Reset(f, 1); - BlockRead(f, size, 2, numread); - map^.w := size[0]; - map^.h := size[1]; - SetLength(map^.tile, map^.w * map^.h); - SetLength(map^.actor, map^.w * map^.h); - BlockRead(f, map^.tile[0], map^.w * map^.h, numread); - BlockRead(f, map^.actor[0], map^.w * map^.h, numread); - Close(f); -end; - -procedure LoadRoom(num:integer); -var - i, j, k: integer; -begin - if (CheckZoneChange(num)) then - begin - SetZone(num); - end; - - // Coloquem el numero d'habitació corresponent al mapa - map.room := max(0, num); - - // Guardem les coordenades i el sentit que te el jugador al entrar a la habitació - player.respawn_x := player.dst_rect.x; - player.respawn_y := player.dst_rect.y; - player.respawn_direction := player.direction; - - // Esborrem la llista de tiles animats - for i:=0 to MAX_ANIMATED_TILES - 1 do - animated_tile[i].enabled := FALSE; - - // Escanejem la habitació en busca de tiles animats - k := 0; - for i:=0 to (ROOM_WIDTH_IN_TILES - 1) do - for j:=0 to (ROOM_HEIGHT_IN_TILES - 1) do - case GetTile(i, j) of - 48 .. 63, 128 .. 143, 160..175, 192..207: - begin - animated_tile[k].enabled := TRUE; - animated_tile[k].x := i * MAP_TILE_WIDTH; - animated_tile[k].y := j * MAP_TILE_HEIGHT; - animated_tile[k].index := GetTile(i, j); - animated_tile[k].frame := 0; - inc(k); - end; - end; - - // Esborrem la llista d'actors actius - for i:=0 to MAX_ACTORS - 1 do - actor[i].enabled := FALSE; - - // Escanejem la habitació en busca d'actors per afegirlos a la llista d'actors actius - k := 0; - for i:=0 to (ROOM_WIDTH_IN_TILES - 1) do - for j:=0 to (ROOM_HEIGHT_IN_TILES - 1) do - begin - case GetActor(i, j) of - CODE_ENEMY_V1U: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 1, 0, 0, UP, k); - - CODE_ENEMY_V2U: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 2, 0, 0, UP, k); - - CODE_ENEMY_V3U: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 3, 0, 0, UP, k); - - CODE_ENEMY_V1D: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 1, 0, 0, DOWN, k); - - CODE_ENEMY_V2D: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 2, 0, 0, DOWN, k); - - CODE_ENEMY_V3D: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 3, 0, 0, DOWN, k); - - CODE_ENEMY_H1L: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 1, 0, 0, 0, LEFT, k); - - CODE_ENEMY_H2L: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 2, 0, 0, 0, LEFT, k); - - CODE_ENEMY_H3L: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 3, 0, 0, 0, LEFT, k); - - CODE_ENEMY_H1R: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 1, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_H2R: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 2, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_H3R: - CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 3, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_W1L: - CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 1 * 16, 1, 0, 0, 0, LEFT, k); - - CODE_ENEMY_W2L: - CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 1 * 16, 2, 0, 0, 0, LEFT, k); - - CODE_ENEMY_W3L: - CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 1 * 16, 3, 0, 0, 0, LEFT, k); - - CODE_ENEMY_W1R: - CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 0 * 16, 1, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_W2R: - CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 0 * 16, 2, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_W3R: - CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 0 * 16, 3, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_SPL: - CreateActor(actor[k], KIND_SPEED_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 3 * 16, 1, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_SPR: - CreateActor(actor[k], KIND_SPEED_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 2 * 16, 1, 0, 0, 0, RIGHT, k); - - CODE_ENEMY_DRP: - CreateActor(actor[k], KIND_DROP_GENERATOR, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 10 * 16, 0, 0, DROP_TIMER, 0, NONE, k); - - CODE_COIN: - CreateActor(actor[k], KIND_COIN, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 12 * 16, 0, 0, 0, 0, NONE, k); - - CODE_HEART: - CreateActor(actor[k], KIND_HEART, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 13 * 16, 1, 0, 0, 0, NONE, k); - - CODE_KEY_RED: - CreateActor(actor[k], KIND_KEY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 14 * 16, 1, 0, 0, 0, NONE, k); - - CODE_LOCK_RED: - CreateActor(actor[k], KIND_LOCK, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 15 * 16, 1, 0, 0, 0, NONE, k); - - CODE_KEY_BLUE: - CreateActor(actor[k], KIND_KEY, 1, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 1 * 16, 14 * 16, 1, 0, 0, 0, NONE, k); - - CODE_LOCK_BLUE: - CreateActor(actor[k], KIND_LOCK, 1, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 1 * 16, 15 * 16, 1, 0, 0, 0, NONE, k); - - CODE_KEY_GREEN: - CreateActor(actor[k], KIND_KEY, 2, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 2 * 16, 14 * 16, 1, 0, 0, 0, NONE, k); - - CODE_LOCK_GREEN: - CreateActor(actor[k], KIND_LOCK, 2, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 2 * 16, 15 * 16, 1, 0, 0, 0, NONE, k); - - CODE_KEY_YELLOW: - CreateActor(actor[k], KIND_KEY, 3, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 3 * 16, 14 * 16, 1, 0, 0, 0, NONE, k); - - CODE_LOCK_YELLOW: - CreateActor(actor[k], KIND_LOCK, 3, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 3 * 16, 15 * 16, 1, 0, 0, 0, NONE, k); - - else - dec(k); - end; - inc(k); - end; -end; - -procedure IniMenu(); -begin - menu.enabled := TRUE; - menu.section := MENU_SECTION_ANIMATION; - - menu.music := Mix_LoadMUS(FILE_MUSIC_MENU); - menu.sound_logo := Mix_LoadWAV(FILE_SOUND_MENU_LOGO); - menu.sound_start := Mix_LoadWAV(FILE_SOUND_MENU_START); - - menu.sprite := OpenPicture(FILE_MENU); - menu.frame := 0; - menu.timer := 200; - - // Fondo - menu.src_rect_fondo.x := 0; - menu.src_rect_fondo.y := 0; - menu.src_rect_fondo.w := 320; - menu.src_rect_fondo.h := 240; - - menu.dst_rect_fondo.x := 0; - menu.dst_rect_fondo.y := 0; - menu.dst_rect_fondo.w := 320; - menu.dst_rect_fondo.h := 240; - - // Logo - menu.src_rect_logo.x := 0; - menu.src_rect_logo.y := 240; - menu.src_rect_logo.w := 260; - menu.src_rect_logo.h := 154; - - menu.dst_rect_logo.x := 30; - menu.dst_rect_logo.y := 30; - menu.dst_rect_logo.w := 260; - menu.dst_rect_logo.h := 154; - - menu.dst_rect_logo_zoom.x := 0; - menu.dst_rect_logo_zoom.y := 0; - menu.dst_rect_logo_zoom.w := 0; - menu.dst_rect_logo_zoom.h := 0; - - // PRESS RETURN TO START - menu.src_rect_text.x := 0; - menu.src_rect_text.y := 394; - menu.src_rect_text.w := 125; - menu.src_rect_text.h := 7; - - menu.dst_rect_text.x := (320 - 125) div 2; - menu.dst_rect_text.y := 195; - menu.dst_rect_text.w := 125; - menu.dst_rect_text.h := 7; - - // JAILGAMES 2016 - menu.src_rect_text2.x := 0; - menu.src_rect_text2.y := 394+7; - menu.src_rect_text2.w := 55; - menu.src_rect_text2.h := 5; - - menu.dst_rect_text2.x := (320 - 55) div 2; - menu.dst_rect_text2.y := 210; - menu.dst_rect_text2.w := 55; - menu.dst_rect_text2.h := 5; - - // Animació - menu.sprite_animation := OpenPicture(FILE_MENU_ANIMATION); - - menu.src_rect_animation.x := 0; - menu.src_rect_animation.y := 0; - menu.src_rect_animation.w := 320; - menu.src_rect_animation.h := 240; - - menu.dst_rect_animation.x := 0; - menu.dst_rect_animation.y := 0; - menu.dst_rect_animation.w := 320; - menu.dst_rect_animation.h := 240; - - menu.animation[0].num_frames := 29; - menu.animation[0].index := 0; - menu.animation[0].timer := 0; - menu.animation[0].speed := 9; - menu.animation[0].loops := FALSE; - - menu.animation[0].frame[ 0] := 0; - menu.animation[0].frame[ 1] := 1; - menu.animation[0].frame[ 2] := 0; - menu.animation[0].frame[ 3] := 1; - menu.animation[0].frame[ 4] := 2; - menu.animation[0].frame[ 5] := 3; - menu.animation[0].frame[ 6] := 4; - menu.animation[0].frame[ 7] := 5; - menu.animation[0].frame[ 8] := 6; - menu.animation[0].frame[ 9] := 7; - menu.animation[0].frame[10] := 8; - menu.animation[0].frame[11] := 9; - menu.animation[0].frame[12] := 10; - menu.animation[0].frame[13] := 11; - menu.animation[0].frame[14] := 12; - menu.animation[0].frame[15] := 13; - menu.animation[0].frame[16] := 14; - menu.animation[0].frame[17] := 15; - menu.animation[0].frame[18] := 16; - menu.animation[0].frame[19] := 17; - menu.animation[0].frame[20] := 18; - menu.animation[0].frame[21] := 19; - menu.animation[0].frame[22] := 20; - menu.animation[0].frame[23] := 21; - menu.animation[0].frame[24] := 22; - menu.animation[0].frame[25] := 23; - menu.animation[0].frame[26] := 24; - menu.animation[0].frame[27] := 25; - menu.animation[0].frame[28] := 26; - - menu.animation[1].num_frames := 23; - menu.animation[1].index := 0; - menu.animation[1].timer := 0; - menu.animation[1].speed := 9; - menu.animation[1].loops := FALSE; - - menu.animation[1].frame[ 0] := 18; - menu.animation[1].frame[ 1] := 26; - menu.animation[1].frame[ 2] := 18; - menu.animation[1].frame[ 3] := 26; - menu.animation[1].frame[ 4] := 18; - menu.animation[1].frame[ 5] := 26; - menu.animation[1].frame[ 6] := 18; - menu.animation[1].frame[ 7] := 26; - menu.animation[1].frame[ 8] := 18; - menu.animation[1].frame[ 9] := 26; - menu.animation[1].frame[10] := 18; - menu.animation[1].frame[11] := 26; - menu.animation[1].frame[12] := 18; - menu.animation[1].frame[13] := 26; - menu.animation[1].frame[14] := 18; - menu.animation[1].frame[15] := 19; - menu.animation[1].frame[16] := 20; - menu.animation[1].frame[17] := 21; - menu.animation[1].frame[18] := 22; - menu.animation[1].frame[19] := 23; - menu.animation[1].frame[20] := 24; - menu.animation[1].frame[21] := 25; - menu.animation[1].frame[22] := 26; -end; - -procedure EndMenu(); -begin - CloseSound(menu.sound_logo); - CloseSound(menu.sound_start); - CloseMusic(menu.music); - ClosePicture(menu.sprite); - ClosePicture(menu.sprite_animation); - menu.enabled:= FALSE; -end; - -procedure IniActors(); -var - i: byte; -begin - for i:=0 to MAX_ACTORS - 1 do - actor[i].enabled := FALSE; - map.sprite_actor := OpenPicture(FILE_ACTORS); -end; - -procedure IniAnimatedTiles(); -var - i: byte; -begin - for i:=0 to MAX_ANIMATED_TILES - 1 do - animated_tile[i].enabled := FALSE; -end; - -procedure IniMap(); -begin - map.src_rect.x := 0; - map.src_rect.y := 0; - map.src_rect.w := 320; - map.src_rect.h := 240; - - map.dst_rect.x := 0; - map.dst_rect.y := 0; - map.dst_rect.w := 320; - map.dst_rect.h := 240; - - LoadMap(@map); -end; - -procedure EndMap(); -begin - ClosePicture(map.sprite_tile); - ClosePicture(map.sprite_actor); - ClosePicture(map.background); -end; - -procedure IniPlayer(); -var - i: byte; -begin - player.sprite := OpenPicture(FILE_PLAYER); - player.dst_rect.x := MAP_TILE_WIDTH * STARTING_PLAYER_TILE_X; - player.dst_rect.y := MAP_TILE_HEIGHT * STARTING_PLAYER_TILE_Y; - player.dst_rect.w := 16; - player.dst_rect.h := 24; - player.src_rect.x := 0; - player.src_rect.y := 0; - player.src_rect.w := player.dst_rect.w; - player.src_rect.h := player.dst_rect.h; - player.direction := RIGHT; - player.respawn_x := player.dst_rect.x; - player.respawn_y := player.dst_rect.y; - player.respawn_direction := player.direction; - player.speed_x := BASE_SPEED; - player.speed_y := 0; - player.can_jump := TRUE; - player.jump_pressed_now := FALSE; - player.jump_pressed_before := FALSE; - player.standing := TRUE; - player.jumpforce := 10; - player.active_animation := 0; - player.enabled := TRUE; - player.cooldown := 0; - player.lifes := 10; - player.coins := 0; - for i:=0 to 5 do player.key[i] := FALSE; - player.sound_jump := Mix_LoadWAV(FILE_SOUND_JUMP); - player.sound_death := Mix_LoadWAV(FILE_SOUND_DEATH); - player.sound_coin := Mix_LoadWAV(FILE_SOUND_COIN); - - player.animation[0].num_frames := 33; - player.animation[0].index := 0; - player.animation[0].timer := 0; - player.animation[0].speed := 6; - player.animation[0].loops := FALSE; - player.animation[0].frame[ 0] := 0; - player.animation[0].frame[ 1] := 1; - player.animation[0].frame[ 2] := 2; - player.animation[0].frame[ 3] := 2; - player.animation[0].frame[ 4] := 1; - player.animation[0].frame[ 5] := 0; - player.animation[0].frame[ 6] := 0; - player.animation[0].frame[ 7] := 1; - player.animation[0].frame[ 8] := 2; - player.animation[0].frame[ 9] := 2; - player.animation[0].frame[10] := 1; - player.animation[0].frame[11] := 0; - player.animation[0].frame[12] := 0; - player.animation[0].frame[13] := 1; - player.animation[0].frame[14] := 2; - player.animation[0].frame[15] := 2; - player.animation[0].frame[16] := 1; - player.animation[0].frame[17] := 0; - player.animation[0].frame[18] := 0; - player.animation[0].frame[19] := 1; - player.animation[0].frame[20] := 2; - player.animation[0].frame[21] := 3; - player.animation[0].frame[22] := 4; - player.animation[0].frame[23] := 4; - player.animation[0].frame[24] := 5; - player.animation[0].frame[25] := 5; - player.animation[0].frame[26] := 4; - player.animation[0].frame[27] := 4; - player.animation[0].frame[28] := 5; - player.animation[0].frame[29] := 5; - player.animation[0].frame[30] := 6; - player.animation[0].frame[31] := 6; - player.animation[0].frame[32] := 7; - - player.animation[1] := player.animation[0]; - - player.animation[2].num_frames := 8; - player.animation[2].index := 0; - player.animation[2].speed := 4; - player.animation[2].loops := FALSE; - player.animation[2].frame[ 0] := 0; - player.animation[2].frame[ 1] := 1; - player.animation[2].frame[ 2] := 2; - player.animation[2].frame[ 3] := 3; - player.animation[2].frame[ 4] := 4; - player.animation[2].frame[ 5] := 5; - player.animation[2].frame[ 6] := 6; - player.animation[2].frame[ 7] := 7; - - player.animation[3] := player.animation[2]; - player.animation[4] := player.animation[2]; - player.animation[5] := player.animation[2]; - - player.animation[6].num_frames := 20; - player.animation[6].index := 0; - player.animation[6].speed := 6; - player.animation[6].loops := FALSE; - player.animation[6].frame[ 0] := 0; - player.animation[6].frame[ 1] := 1; - player.animation[6].frame[ 2] := 2; - player.animation[6].frame[ 3] := 3; - player.animation[6].frame[ 4] := 4; - player.animation[6].frame[ 5] := 5; - player.animation[6].frame[ 6] := 6; - player.animation[6].frame[ 7] := 7; - player.animation[6].frame[ 8] := 7; - player.animation[6].frame[ 9] := 7; - player.animation[6].frame[10] := 7; - player.animation[6].frame[11] := 7; - player.animation[6].frame[12] := 7; - player.animation[6].frame[13] := 7; - player.animation[6].frame[14] := 7; - player.animation[6].frame[15] := 7; - player.animation[6].frame[16] := 7; - player.animation[6].frame[17] := 7; - player.animation[6].frame[18] := 7; - player.animation[6].frame[19] := 7; - - player.animation[7] := player.animation[6]; -end; - -procedure EndPlayer(); -begin - ClosePicture(player.sprite); - CloseSound(player.sound_jump); - CloseSound(player.sound_death); - CloseSound(player.sound_coin); -end; - -procedure IniHud(); -begin - hud.sprite := OpenPicture(FILE_HUD); - hud.src_rect.x := 0; - hud.src_rect.y := 0; - hud.src_rect.w := 320; - hud.src_rect.h := 16; - - hud.dst_rect.x := 0; - hud.dst_rect.y := 224; - hud.dst_rect.w := 320; - hud.dst_rect.h := 16; - - hud.num_src_rect.x := 0; - hud.num_src_rect.y := 16; - hud.num_src_rect.w := 5; - hud.num_src_rect.h := 5; - - hud.num_dst_rect.x := 0; - hud.num_dst_rect.y := 16; - hud.num_dst_rect.w := 5; - hud.num_dst_rect.h := 5; - - hud.bignum_src_rect.x := 0; - hud.bignum_src_rect.y := 21; - hud.bignum_src_rect.w := 7; - hud.bignum_src_rect.h := 7; - - hud.bignum_dst_rect.x := 0; - hud.bignum_dst_rect.y := 21; - hud.bignum_dst_rect.w := 7; - hud.bignum_dst_rect.h := 7; -end; - -procedure EndHud(); -begin - ClosePicture(hud.sprite); -end; - -procedure IniGame(zone: byte); -begin - game.sound_drop_enemy := Mix_LoadWAV(FILE_SOUND_DROP_ENEMY); - game.sound_drop_splat := Mix_LoadWAV(FILE_SOUND_DROP_SPLAT); - game.enabled := TRUE; - game.zone := zone; - - // Inicialitzar jugador - IniPlayer(); - - // Inicialitza hud - IniHud(); - - // Establir el color d'esborrat - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - - // Inicialitza actors - IniActors(); - - // Inicialitza tiles animats - IniAnimatedTiles(); - - // Inicialitza mapa - IniMap(); - SetMapGFX(zone); - SetMapMusic(zone); -end; - -procedure EndGame(); -begin - EndPlayer(); - EndHud(); - EndMap(); - CloseSound(game.sound_drop_enemy); - CloseSound(game.sound_drop_splat); - CloseMusic(game.music); - game.enabled := FALSE; -end; - -procedure KillPlayer(); -begin - player.enabled := FALSE; - player.cooldown := COOLDOWN_TIME; - - // Establir animació de mort - if (player.direction = LEFT) then - SetPlayerAnimation(PLAYER_ANIMATION_DYING_LEFT) - else - SetPlayerAnimation(PLAYER_ANIMATION_DYING_RIGHT); - - - Mix_PlayChannel(-1, player.sound_death, 0); -end; - -function OnFloor():boolean; -//[27/08/2016] [DOC] [BEGIN] -var - tile_on_right_foot, tile_on_left_foot, - tile_under_right_foot, tile_under_left_foot : byte; - - i_am_above_platform, i_am_above_travesable, - i_am_on_background : boolean; -begin - tile_under_left_foot := ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT); - tile_under_right_foot := ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT); - - i_am_above_platform := (tile_under_left_foot = TILE_PLATFORM) or (tile_under_right_foot = TILE_PLATFORM); - i_am_above_travesable := (tile_under_left_foot = TILE_TRAVESABLE_PLATFORM) or (tile_under_right_foot = TILE_TRAVESABLE_PLATFORM); - - tile_on_left_foot := ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h-1) div MAP_TILE_HEIGHT); - tile_on_right_foot := ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h-1) div MAP_TILE_HEIGHT); - - i_am_on_background := (tile_on_left_foot = TILE_BACKGROUND) and (tile_on_right_foot = TILE_BACKGROUND); - - if ( ( i_am_above_platform or i_am_above_travesable ) and i_am_on_background ) then - OnFloor := TRUE - else - OnFloor := FALSE; -//[27/08/2016] [DOC] [END] - - {if (ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) then - OnFloor := TRUE - else - OnFloor := FALSE;} -end; - -procedure MoveActors(); -var - i, k: byte; -begin - for i:=0 to MAX_ACTORS - 1 do - if actor[i].enabled then - case actor[i].kind of - KIND_FLYING_ENEMY: - begin - case actor[i].direction of - RIGHT: - begin - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x + actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) then - actor[i].direction := LEFT; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); - actor[i].direction := LEFT; - end; - end; - - LEFT: - begin - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x - actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x) < 0 then - actor[i].direction := RIGHT; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); - actor[i].direction := RIGHT; - end; - end; - - DOWN: - begin - // Calculem la nova posició - actor[i].dst_rect.y := actor[i].dst_rect.y + actor[i].speed_y; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.y + actor[i].dst_rect.h > GAME_WINDOW_HEIGHT) then - actor[i].direction := UP; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.y := actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) mod MAP_TILE_WIDTH); - actor[i].direction := UP; - end; - end; - - UP: - begin - // Calculem la nova posició - actor[i].dst_rect.y := actor[i].dst_rect.y - actor[i].speed_y; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.y < 0) then - actor[i].direction := DOWN; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.y := actor[i].dst_rect.y + (MAP_TILE_WIDTH - (actor[i].dst_rect.y mod MAP_TILE_WIDTH)); - actor[i].direction := DOWN; - end; - end; - end; - - actor[i].frame := (actor[i].frame + 1) mod 24; - if (actor[i].direction = UP) then - actor[i].src_rect.y := 4 * 16; - if (actor[i].direction = DOWN) then - actor[i].src_rect.y := 5 * 16; - if (actor[i].direction = LEFT) then - actor[i].src_rect.y := 7 * 16; - if (actor[i].direction = RIGHT) then - actor[i].src_rect.y := 6 * 16; - actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; - end; - - KIND_WALKING_ENEMY: - begin - case actor[i].direction of - RIGHT: - begin - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x + actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) then - actor[i].direction := LEFT; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); - actor[i].direction := LEFT; - end; - - // Arriba a la vora, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 3) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then - actor[i].direction := LEFT; - end; - - LEFT: - begin - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x - actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x) < 0 then - actor[i].direction := RIGHT; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); - actor[i].direction := RIGHT; - end; - - // Arriba a la vora, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + 3) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then - actor[i].direction := RIGHT; - end; - end; - - // Animacio - actor[i].frame := (actor[i].frame + 1) mod 48; - if (actor[i].direction = LEFT) then - actor[i].src_rect.y := 1 * 16 - else - actor[i].src_rect.y := 0 * 16; - actor[i].src_rect.x := (actor[i].frame div 8) * actor[i].dst_rect.w; - end; - - KIND_SPEED_ENEMY: - begin - case actor[i].direction of - RIGHT: - begin - // Mirem si estem en la mateixa altura que el jugador i fem que es meneje més ràpid - if (actor[i].dst_rect.y + 8 > player.dst_rect.y) - and (actor[i].dst_rect.y + 8 < player.dst_rect.y + player.dst_rect.h - 1) - and (player.can_jump) then - actor[i].speed_x := 3 - else - actor[i].speed_x := 1; - - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x + actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) then - actor[i].direction := LEFT; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); - actor[i].direction := LEFT; - end; - - // Arriba a la vora, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 3) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then - actor[i].direction := LEFT; - end; - - LEFT: - begin - // Mirem si estem en la mateixa altura que el jugador i fem que es meneje més ràpid - if (actor[i].dst_rect.y + 8 > player.dst_rect.y) - and (actor[i].dst_rect.y + 8 < player.dst_rect.y + player.dst_rect.h - 1) - and (player.can_jump) then - actor[i].speed_x := 3 - else - actor[i].speed_x := 1; - - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x - actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x) < 0 then - actor[i].direction := RIGHT; - - // Colisió amb el mapa, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); - actor[i].direction := RIGHT; - end; - - // Arriba a la vora, correcció a l'ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + 3) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then - actor[i].direction := RIGHT; - end; - end; - - // Animacio - actor[i].frame := (actor[i].frame + 1) mod 48; - if (actor[i].direction = LEFT) then - actor[i].src_rect.y := 2 * 16 - else - actor[i].src_rect.y := 3 * 16; - actor[i].src_rect.x := (actor[i].frame div 8) * actor[i].dst_rect.w; - end; - - KIND_MOBILE_PLATFORM: - begin - case actor[i].direction of - RIGHT: - begin - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x + actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) then - actor[i].direction := LEFT; - - // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit - if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); - actor[i].direction := LEFT; - end; - end; - - LEFT: - begin - // Calculem la nova posició - actor[i].dst_rect.x := actor[i].dst_rect.x - actor[i].speed_x; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.x < 0) then - actor[i].direction := RIGHT; - - // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); - actor[i].direction := RIGHT; - end; - end; - - DOWN: - begin - // Calculem la nova posició - actor[i].dst_rect.y := actor[i].dst_rect.y + actor[i].speed_y; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.y + actor[i].dst_rect.h > GAME_WINDOW_HEIGHT) then - actor[i].direction := UP; - - // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.y := actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) mod MAP_TILE_WIDTH); - actor[i].direction := UP; - end; - end; - - UP: - begin - // Calculem la nova posició - actor[i].dst_rect.y := actor[i].dst_rect.y - actor[i].speed_y; - - // Si eix per la vora, canvi de sentit - if (actor[i].dst_rect.y < 0) then - actor[i].direction := DOWN; - - // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.y := actor[i].dst_rect.y + (MAP_TILE_WIDTH - (actor[i].dst_rect.y mod MAP_TILE_WIDTH)); - actor[i].direction := DOWN; - end; - end; - end; - end; - - KIND_DROP_GENERATOR: - begin - if (actor[i].timer > 0) then - dec(actor[i].timer) - else - // Si el contador arriba a 0, creem un actor KIND_DROP_ENEMY - begin - actor[i].timer := 32000; - k := 0; - while (actor[k].enabled) do inc(k); - CreateActor(actor[k], KIND_DROP_ENEMY, 0, actor[i].dst_rect.x, actor[i].dst_rect.y, 16, 16, 0, 8 * 16, 0, 2, 0, 0, DOWN, i); - Mix_PlayChannel(-1, game.sound_drop_enemy, 0); - end; - - // Animacio - actor[i].frame := (actor[i].frame + 1) mod 24; - if (actor[i].timer > (DROP_TIMER - 25)) then - // no el pintem. Posem el frame 6 que està buit - actor[i].src_rect.x := (6 * actor[i].dst_rect.w) - else - actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; - end; - - KIND_DROP_ENEMY: - begin - // Calculem la nova posició - actor[i].dst_rect.y := actor[i].dst_rect.y + actor[i].speed_y; - - // Si eix per la vora, adios i avisa al pare - if (actor[i].dst_rect.y + actor[i].dst_rect.h > GAME_WINDOW_HEIGHT) then - begin - actor[i].enabled := FALSE; - actor[actor[i].parent].timer := DROP_TIMER; - end; - - // Colisió amb el mapa, correcció al ultim pixel bo, transforma en KIND_DROP_SPLAT - if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) - or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then - begin - actor[i].dst_rect.y := actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) mod MAP_TILE_WIDTH); - actor[i].kind := KIND_DROP_SPLAT; - actor[i].frame := 0; - actor[i].timer := 30; - actor[i].src_rect.y := 11 * 16; - Mix_PlayChannel(-1, game.sound_drop_splat, 0); - end; - - // Animacio - actor[i].frame := (actor[i].frame + 1) mod 24; - actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; - end; - - KIND_DROP_SPLAT: - begin - //if (actor[i].timer > 0) then - if (actor[i].frame < 23) then - // Si encara te temps, pintem la animació - begin - dec(actor[i].timer); - actor[i].frame := (actor[i].frame + 1) mod 24; - actor[i].src_rect.x := ((actor[i].frame div 4) + 0) * actor[i].dst_rect.w; - end - else - begin - actor[i].enabled := FALSE; - actor[actor[i].parent].timer := DROP_TIMER; - end; - end; - - KIND_COIN: - begin - actor[i].frame := (actor[i].frame + 1) mod 32; - actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; - end; - - KIND_HEART: - begin - actor[i].frame := (actor[i].frame + 1) mod 32; - actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; - end; - - KIND_KEY: - begin - //actor[i].frame := (actor[i].frame + 1) mod 32; - //actor[i].src_rect.x := (actor[i].frame div 32) * actor[i].dst_rect.w; - end; - - KIND_LOCK: - begin - //actor[i].frame := (actor[i].frame + 1) mod 32; - //actor[i].src_rect.x := (actor[i].frame div 32) * actor[i].dst_rect.w; - end; - end; -end; - -procedure SetPlayerDirection(direction: integer); -begin - if (direction <> player.direction) then - begin - player.direction := direction; - player.speed_x := 0; - end; -end; - -procedure MovePlayer(direction: integer); -begin - case direction of - UP: - begin - // Si pot saltar, aleshores - if (OnFloor and player.can_jump) then - begin - // Salta i ja no pot saltar (fins que toque terra i/o soltes el botó) - player.can_jump := FALSE; - - // No estem quets - player.standing := FALSE; - - // Pilla velocitat negativa per a pujar cap amunt - player.speed_y := -(player.jumpforce); - - // Calculem la nova posició - player.dst_rect.y := player.dst_rect.y + player.speed_y; - - // Soroll de saltar - Mix_PlayChannel(-1, player.sound_jump, 0); - end; - - // Nou frame d'animació - if (player.direction = LEFT) then - SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_LEFT) - else - if (player.direction = RIGHT) then - SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_RIGHT); - end; - - RIGHT: - begin - // Per a poder dibuixar el bot en el sentit que toca - SetPlayerDirection(RIGHT); - - // No estem quets - player.standing := FALSE; - - // Incrementem la velocitat horitzontal - player.speed_x := min(player.speed_x + 1, MAX_SPEED); - - // Calculem la nova posició - player.dst_rect.x := player.dst_rect.x + ((player.speed_x div RATIO_SPEED) + 1); - - // Selecció de l'animació - if (player.speed_y = 0) then - // Animació de caminar - SetPlayerAnimation(PLAYER_ANIMATION_WALKING_RIGHT) - else - // Animació de saltar - SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_RIGHT); - end; - - LEFT : - begin - // Per a poder dibuixar el bot en el sentit que toca - SetPlayerDirection(LEFT); - - // No estem quets - player.standing := FALSE; - - // Incrementem la velocitat horitzontal - player.speed_x := min(player.speed_x + 1, MAX_SPEED); - - // Calculem la nova posició - player.dst_rect.x := player.dst_rect.x - ((player.speed_x div RATIO_SPEED) + 1); - - // Selecció de l'animació - if (player.speed_y = 0) then - // Animació de caminar - SetPlayerAnimation(PLAYER_ANIMATION_WALKING_LEFT) - else - // Animació de saltar - SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_LEFT); - end; - end; - - // Calcul del frame d'animació - Animate(player.animation[player.active_animation], player.src_rect); -end; - -procedure ApplyGravity(); -begin - // Si toca piso aleshores - if (OnFloor) then - begin - // Totes les forces verticals paren - player.speed_y := 0; - // Podem saltar - player.can_jump := TRUE; - end - else - begin - // Si no toca piso aleshores s'incrementa la velocitat vertical - player.speed_y := player.speed_y + GRAVITY; - - // La velocitat no pot ser mai superior a la altura d'un tile del mapa, per a que no els atravesse - //player.speed_y := max(min(player.speed_y, MAX_SPEED_Y), -(MAX_SPEED_Y)); - player.speed_y := min(player.speed_y, MAX_SPEED_Y); - - // Calculem la nova posició - player.dst_rect.y := player.dst_rect.y + player.speed_y; - end; -end; - -procedure DrawSprite (sprite:PSDL_Texture; src_rect, dst_rect: TSDL_Rect); -begin - SDL_RenderCopy(renderer, sprite, @src_rect, @dst_rect); -end; - -procedure DrawMap(map:Tmap); -var - i, j: byte; - src_rect1: TSDL_Rect; - dst_rect1: TSDL_Rect; -begin - src_rect1.w := MAP_TILE_WIDTH; - src_rect1.h := MAP_TILE_HEIGHT; - dst_rect1.w := MAP_TILE_WIDTH; - dst_rect1.h := MAP_TILE_HEIGHT; - - for i:=0 to (ROOM_WIDTH_IN_TILES - 1) do - for j:=0 to (ROOM_HEIGHT_IN_TILES - 1) do - begin - src_rect1.x := (GetTile(i, j) mod 16) * MAP_TILE_WIDTH; - src_rect1.y := (GetTile(i, j) div 16) * MAP_TILE_HEIGHT; - dst_rect1.x := i * MAP_TILE_WIDTH; - dst_rect1.y := j * MAP_TILE_HEIGHT; - SDL_RenderCopy(renderer, map.sprite_tile, @src_rect1, @dst_rect1); - end; - - i := 0; - while animated_tile[i].enabled do - begin - src_rect1.x := ((animated_tile[i].index mod 16) * MAP_TILE_WIDTH) + ((animated_tile[i].frame div 8) * MAP_TILE_WIDTH); - src_rect1.y := (animated_tile[i].index div 16) * MAP_TILE_HEIGHT; - dst_rect1.x := animated_tile[i].x; - dst_rect1.y := animated_tile[i].y; - animated_tile[i].frame := (animated_tile[i].frame + 1) mod 16; - SDL_RenderCopy(renderer, map.sprite_tile, @src_rect1, @dst_rect1); - inc(i); - end; -end; - -procedure DrawHud(); -begin - // Pinta el fondo del marcador - DrawSprite(hud.sprite, hud.src_rect, hud.dst_rect); - - // Pinta el numero de vides - hud.bignum_src_rect.x := ((player.lifes mod 100) div 10) * hud.bignum_src_rect.w; - hud.bignum_dst_rect.y := 229; - hud.bignum_dst_rect.x := 88; - DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); - - hud.bignum_src_rect.x := (player.lifes mod 10) * hud.bignum_src_rect.w; - hud.bignum_dst_rect.x := 96; - DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); - - // Pinta el numero de monedes - hud.bignum_src_rect.x := (player.coins div 100) * hud.bignum_src_rect.w; - hud.bignum_dst_rect.y := 229; - hud.bignum_dst_rect.x := 258; - DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); - - hud.bignum_src_rect.x := ((player.coins mod 100) div 10) * hud.bignum_src_rect.w; - hud.bignum_dst_rect.x := 258+8; - DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); - - hud.bignum_src_rect.x := (player.coins mod 10) * hud.bignum_src_rect.w; - hud.bignum_dst_rect.x := 258+16; - DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); - - if prog.debug then - begin - // Pinta el valor x,y del jugador - hud.num_src_rect.x := (player.dst_rect.x div 100) * hud.num_src_rect.w; - hud.num_dst_rect.y := 1; - hud.num_dst_rect.x := 1; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := ((player.dst_rect.x mod 100) div 10) * hud.num_src_rect.w; - hud.num_dst_rect.x := 5; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := (player.dst_rect.x mod 10) * hud.num_src_rect.w; - hud.num_dst_rect.x := 9; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := (player.dst_rect.y div 100) * hud.num_src_rect.w; - hud.num_dst_rect.x := 17; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := ((player.dst_rect.y mod 100) div 10) * hud.num_src_rect.w; - hud.num_dst_rect.x := 21; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := (player.dst_rect.y mod 10) * hud.num_src_rect.w; - hud.num_dst_rect.x := 25; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - // Pinta el valor de onfloor - if (OnFloor) then - hud.num_src_rect.x := 1 * hud.num_src_rect.w - else - hud.num_src_rect.x := 0 * hud.num_src_rect.w; - hud.num_dst_rect.y := 1; - hud.num_dst_rect.x := 33; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT)) * hud.num_src_rect.w; - hud.num_dst_rect.x := 37; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT)) * hud.num_src_rect.w; - hud.num_dst_rect.x := 41; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - // Pinta el numero d'habitació - hud.num_src_rect.x := (map.room div 100) * hud.num_src_rect.w; - hud.num_dst_rect.y := 1; - hud.num_dst_rect.x := 49; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := ((map.room mod 100) div 10) * hud.num_src_rect.w; - hud.num_dst_rect.x := 53; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - - hud.num_src_rect.x := (map.room mod 10) * hud.num_src_rect.w; - hud.num_dst_rect.x := 57; - DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); - end; -end; - -procedure CheckPlayerCollisionWithMap(); -var - tile_on_left_foot, tile_on_right_foot : byte; // [27/05/2016] [DOC] - i_am_on_platform, i_am_on_travesable : boolean; // [27/05/2016] [DOC] -begin - // Si eix per baix, recalcula posició i canvi de pantalla - if (player.dst_rect.y > GAME_WINDOW_HEIGHT) then - begin - // Coloquem al jugador dalt de tot - player.dst_rect.y := 1; - - // Canvi de pantalla - LoadRoom(map.room + 12); - end; - - // Si eix per dalt, recalcula posició i canvi de pantalla - if ((player.dst_rect.y + player.dst_rect.h - 1) < 0) then - begin - // Recoloca el personat - player.dst_rect.y := GAME_WINDOW_HEIGHT - player.dst_rect.h; - - // Canvi de pantalla - LoadRoom(map.room - 12); - end; - - // Si eix per la vora, recalcula posició i canvi de pantalla - if (player.dst_rect.x > GAME_WINDOW_WIDTH) then - begin - // Coloquem al jugador en la entrada de la nova pantalla - player.dst_rect.x := 0; - - // Canvi de pantalla - LoadRoom(map.room + 1); - end; - - // Si eix per la vora, recalcula posició i canvi de pantalla - if ((player.dst_rect.x + player.dst_rect.w - 1) < 0) then - begin - // El posem al borde dret - player.dst_rect.x := GAME_WINDOW_WIDTH - player.dst_rect.w; - - // Canvi de pantalla - LoadRoom(map.room - 1); - end; - - // Mirem si colisionem cap avall i corregim - //[27/05/2016] [DOC] [BEGIN] - tile_on_left_foot := ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT); - tile_on_right_foot := ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT); - - i_am_on_platform := (tile_on_left_foot = TILE_PLATFORM) or (tile_on_right_foot = TILE_PLATFORM); - i_am_on_travesable := (tile_on_left_foot = TILE_TRAVESABLE_PLATFORM) or (tile_on_right_foot = TILE_TRAVESABLE_PLATFORM); - - if ( (player.was_on_background) and (player.speed_y > 0) and ( i_am_on_platform or i_am_on_travesable ) ) then - begin - // Corregim la posicio - player.dst_rect.y := player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) mod MAP_TILE_HEIGHT) - 1; - - // Ja podem saltar - player.can_jump := TRUE; - end; - - player.was_on_background := (tile_on_left_foot = TILE_BACKGROUND) and (tile_on_right_foot = TILE_BACKGROUND); - //[27/05/2016] [DOC] [END] - - {if player.speed_y > 0 then - if (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) then - begin - // Corregim la posicio - player.dst_rect.y := player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) mod MAP_TILE_HEIGHT) - 1; - - // Ja podem saltar - player.can_jump := TRUE; - end; - - if (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) then - begin - // Corregim la posicio - player.dst_rect.y := player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) mod MAP_TILE_HEIGHT) - 1; - - // Ja podem saltar - player.can_jump := TRUE; - end;} - - // Mirem si colisionem cap amunt i corregim - if (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) then - // Corregim la posicio - player.dst_rect.y := player.dst_rect.y + (MAP_TILE_HEIGHT - (player.dst_rect.y mod MAP_TILE_HEIGHT)); - - // Una vegada em permes la colisió amunt o avall, al haver un marge de 3 pixels pot ser que estiguem dins d'una paret. S'ha de corregir aquest offset - // Mirem les colisions laterals - if (ReadMapTile(player.dst_rect.x div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile(player.dst_rect.x div MAP_TILE_WIDTH, (player.dst_rect.y + (player.dst_rect.h div 2)) div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile(player.dst_rect.x div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) then - player.dst_rect.x := player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x mod MAP_TILE_WIDTH)); - - if (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) div MAP_TILE_WIDTH, (player.dst_rect.y + (player.dst_rect.h div 2)) div MAP_TILE_HEIGHT) = TILE_PLATFORM) - or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) then - player.dst_rect.x := player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) mod MAP_TILE_WIDTH); - - // Comprovar si toca alguna part del mapa de les que maten - if (ReadMapTile((player.dst_rect.x + 8) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 12) div MAP_TILE_HEIGHT) = TILE_KILLING_PLATFORM) then - if player.enabled then - KillPlayer(); -end; - -{procedure CheckPlayerCollisionWithActors(); -var - i, collision: byte; - //collision_top, collision_bottom, collision_left, collision_right: boolean; -begin - for i:=0 to MAX_ACTORS - 1 do - if actor[i].enabled then - begin - collision := NO_COLLISION; - if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - collision := LEFT_COLLISION; - - if((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - collision := RIGHT_COLLISION; - - if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - collision := LEFT_COLLISION; - - if ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - collision := RIGHT_COLLISION; - - if (collision <> NO_COLLISION) then - case actor[i].kind of - KIND_FLYING_ENEMY, KIND_WALKING_ENEMY, KIND_DROP_ENEMY, KIND_SPEED_ENEMY: - begin - if (player.enabled) then - KillPlayer(); - end; - - KIND_COIN: - begin - inc(player.coins); - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); - Mix_PlayChannel(-1, player.sound_coin, 0); - end; - - KIND_HEART: - begin - inc(player.lifes); - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); - Mix_PlayChannel(-1, player.sound_coin, 0); - end; - - KIND_KEY: - begin - player.key[0] := TRUE;; - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); - Mix_PlayChannel(-1, player.sound_coin, 0); - end; - - KIND_LOCK: - begin - // Si tenim clau - if (player.key[0]) then - begin - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div MAP_TILE_WIDTH), (actor[i].dst_rect.y div MAP_TILE_HEIGHT), 0); - end - else - begin - if collision = LEFT_COLLISION then - begin - player.dst_rect.x := player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x mod MAP_TILE_WIDTH)); - end - else - begin - player.dst_rect.x := player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) mod MAP_TILE_WIDTH); - end; - end; - end; - end; - end; -end;} - -procedure CheckPlayerCollisionWithActors(); -var - i: byte; -begin - for i:=0 to MAX_ACTORS - 1 do - if actor[i].enabled then - case actor[i].kind of - KIND_FLYING_ENEMY, KIND_WALKING_ENEMY, KIND_DROP_ENEMY, KIND_SPEED_ENEMY: - begin - if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - if (player.enabled) then - KillPlayer(); - end; - - KIND_COIN: - begin - if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - begin - inc(player.coins); - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); - Mix_PlayChannel(-1, player.sound_coin, 0); - end; - end; - - KIND_HEART: - begin - if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - begin - inc(player.lifes); - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); - Mix_PlayChannel(-1, player.sound_coin, 0); - end; - end; - - KIND_KEY: - begin - if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then - begin - player.key[actor[i].id] := TRUE;; - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); - Mix_PlayChannel(-1, player.sound_coin, 0); - end; - end; - - KIND_LOCK: - // Les colisions amb aquest actor no tenen en compte el ENEMY_HITBOX_REDUCTION - begin - // El jugador colisiona amb el actor per l'esquerra del jugador - if ((actor[i].dst_rect.x + actor[i].dst_rect.w > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x + actor[i].dst_rect.w > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y > player.dst_rect.y) and (actor[i].dst_rect.y < player.dst_rect.y + player.dst_rect.h)) then - // Si tenim clau - if (player.key[actor[i].id]) then - begin - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div MAP_TILE_WIDTH), (actor[i].dst_rect.y div MAP_TILE_HEIGHT), 0); - end - // Si no tenim clau - else - begin - player.dst_rect.x := player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x mod MAP_TILE_WIDTH)); - end; - - // El jugador colisiona amb el actor per la dreta del jugador - if ((actor[i].dst_rect.x > player.dst_rect.x) and (actor[i].dst_rect.x < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y + actor[i].dst_rect.h > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h < player.dst_rect.y + player.dst_rect.h)) - or - ((actor[i].dst_rect.x > player.dst_rect.x) and (actor[i].dst_rect.x < player.dst_rect.x + player.dst_rect.w) and - (actor[i].dst_rect.y > player.dst_rect.y) and (actor[i].dst_rect.y < player.dst_rect.y + player.dst_rect.h)) then - // Si tenim clau - if (player.key[actor[i].id]) then - begin - actor[i].enabled := FALSE; - SetActor((actor[i].dst_rect.x div MAP_TILE_WIDTH), (actor[i].dst_rect.y div MAP_TILE_HEIGHT), 0); - end - // Si no tenim clau - else - begin - player.dst_rect.x := player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) mod MAP_TILE_WIDTH); - end; - end; - end; -end; - -procedure SetProgSection(section:byte); -begin - case section of - SECTION_MENU: - begin - prog.section := SECTION_MENU; - IniMenu(); - EndGame(); - end; - - SECTION_GAME: - begin - prog.section := SECTION_GAME; - IniGame(ZONE_VOLCANO); - EndMenu; - end; - - SECTION_QUIT: - begin - prog.section := SECTION_QUIT; - EndGame; - EndMenu; - end; - end; -end; - -procedure IniProgram(); -begin - prog.music_enabled := TRUE; - prog.filter := TRUE; - SetProgSection(SECTION_MENU); - prog.debug := FALSE; - - if (prog.music_enabled) then - Mix_VolumeMusic(100) - else - Mix_VolumeMusic(0); - - prog.sprite := OpenPicture(FILE_FILTER); - - prog.src_rect.x := 0; - prog.src_rect.y := 0; - prog.src_rect.w := 640; - prog.src_rect.h := 480; - - prog.dst_rect.x := 0; - prog.dst_rect.y := 0; - prog.dst_rect.w := 640; - prog.dst_rect.h := 480; -end; - -procedure EndProgram(); -begin - ClosePicture(prog.sprite); - EndGame(); - EndMenu(); -end; - -begin - // Inicialitzar SDL en general i el video en particular - fullscreen := false; - SDL_Init(SDL_INIT_EVERYTHING); - window := SDL_CreateWindow(WINDOW_TITLE + BUILD, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); - renderer := SDL_CreateRenderer(window, -1, 0); - SDL_RenderSetLogicalSize(renderer, 320, 240); - - // Inicialitzar SDL_Image (càrrega de PNGs) - IMG_Init(IMG_INIT_PNG); - - // Inicialitzar audio - Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024); - Mix_AllocateChannels(8); - - // Inicialitzar el programa - IniProgram(); - - // Establir el color d'esborrat - SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - - // Inicialitza variables generals - quit := false; - delta_time := SDL_GetTicks(); - - // Bucle de programa - while not quit do - begin - case prog.section of - SECTION_GAME: - begin - // Inicialitza habitació - LoadRoom(STARTING_ROOM); - - // Conecta la musica - Mix_PlayMusic(game.music, -1); - - // Bucle de joc - while game.enabled do - begin - while SDL_PollEvent(@e) > 0 do - begin - // Si arriva el event de tancar la aplicació, eixim del bucle - if (e.type_ = SDL_QUITEV) then - begin - quit := true; - SetProgSection(SECTION_MENU); - break; - end - else - if ((e.type_ = SDL_KEYDOWN) and (e.key._repeat = 0)) then - case e.key.keysym.scancode of - SDL_SCANCODE_ESCAPE: - begin - SetProgSection(SECTION_MENU); - end; - - SDL_SCANCODE_F: - begin - if ( fullscreen ) then - begin - SDL_SetWindowFullscreen(window, 0); - SDL_ShowCursor(1); - fullscreen := false; - end - else - begin - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_ShowCursor(0); - fullscreen := true; - end; - end; - - SDL_SCANCODE_W: - begin - LoadRoom(map.room - 12); - end; - - SDL_SCANCODE_A: - begin - LoadRoom(map.room - 1); - end; - - SDL_SCANCODE_S: - begin - LoadRoom(map.room + 12); - end; - - SDL_SCANCODE_D: - begin - LoadRoom(map.room + 1); - end; - - SDL_SCANCODE_G: - begin - player.lifes := 255; - end; - - SDL_SCANCODE_M: - begin - prog.music_enabled := not(prog.music_enabled); - if (prog.music_enabled) then - Mix_VolumeMusic(100) - else - Mix_VolumeMusic(0); - end; - - SDL_SCANCODE_T: - begin - IniPlayer(); - LoadRoom(TEST_ROOM); - end; - - SDL_SCANCODE_F1: - begin - prog.debug := not(prog.debug); - end; - - SDL_SCANCODE_F2: - begin - prog.filter := not(prog.filter); - end; - end; - end; - - if ((SDL_GetTicks() - delta_time) > GAME_SPEED) then - begin - // Agafar el array de tecles - keys := SDL_GetKeyboardState(nil); - - // Mirem si esta apretant el botó de saltar. Per tal d'evitar repeticions en aquest boto - if (keys[SDL_SCANCODE_UP] = 0) then - player.jump_pressed_now := FALSE - else - player.jump_pressed_now := TRUE; - - // Si el jugador està deshabilitat, anem reduint el temps d'espera i canviant el frame de la animació de mort - if not(player.enabled) then - if (player.cooldown > 0) then - begin - dec(player.cooldown); - Animate(player.animation[player.active_animation], player.src_rect); - end - else - // Ha acabat el temps d'estar mort. Revivim al jugador - begin - player.enabled := TRUE; - - // Coloquem al jugador en el sentit que tenia quan va entrar a la habitació - if (player.respawn_direction = LEFT) then - begin - SetPlayerAnimation(PLAYER_ANIMATION_STANDING_LEFT); - player.direction := LEFT; - end; - if (player.respawn_direction = RIGHT) then - begin - SetPlayerAnimation(PLAYER_ANIMATION_STANDING_RIGHT); - player.direction := RIGHT; - end; - - // Coloquem al jugador en les coordenades per on va entrar - player.dst_rect.x := min(player.respawn_x, GAME_WINDOW_WIDTH - player.dst_rect.w); - player.dst_rect.y := player.respawn_y; - - // Recarreguem la habitació - LoadRoom(map.room); - - if (player.lifes > 0) then - // Descontem una vida - dec(player.lifes) - else - // Si no li queden vides, eixim al menu - SetProgSection(SECTION_MENU); - end; - - // Comprovem les tecles que ens interesen i actuem en consequència - if (keys[SDL_SCANCODE_RIGHT] = 1) and (player.enabled) then - MovePlayer(RIGHT); - if (keys[SDL_SCANCODE_LEFT] = 1) and (keys[SDL_SCANCODE_RIGHT] = 0) and (player.enabled) then - MovePlayer(LEFT); - if (keys[SDL_SCANCODE_UP] = 1) and (player.enabled) and not(player.jump_pressed_before) then - MovePlayer(UP); - player.jump_pressed_before := player.jump_pressed_now; - - // Mirem si no estem fent cap a cap costat i reduim la velocitat horitzontal - if ((keys[SDL_SCANCODE_RIGHT] = 0) and (keys[SDL_SCANCODE_LEFT] = 0) and (player.enabled)) then - begin - player.speed_x := 0; - - // Estem quets - player.standing := TRUE; - - // Posem la animació d'estar quet si no estem saltant - //if (player.speed_y = 0) then - if (player.can_jump) then - begin - if (player.direction = LEFT) then - SetPlayerAnimation(PLAYER_ANIMATION_STANDING_LEFT) - else - if (player.direction = RIGHT) then - SetPlayerAnimation(PLAYER_ANIMATION_STANDING_RIGHT); - Animate(player.animation[player.active_animation], player.src_rect); - end; - end; - - // Moure els actors - MoveActors(); - - // Apliquem la gravetat - if (player.enabled) then ApplyGravity(); - - // Comprovar colisions amb els actors - if (player.enabled) then CheckPlayerCollisionWithActors(); - - // Comprovar colisions amb el mapejat - CheckPlayerCollisionWithMap(); - - SDL_RenderSetLogicalSize(renderer, 320, 240); - - // Borrem pantalla - SDL_RenderClear(renderer); - - // Pintem el fondo - DrawSprite(map.background, map.src_rect, map.dst_rect); - - // Pinta el mapa - DrawMap(map); - - // Pintem el jugador - DrawSprite(player.sprite, player.src_rect, player.dst_rect); - - // Pintem els actors - for i:=0 to MAX_ACTORS - 1 do - if (actor[i].enabled) then - DrawSprite(map.sprite_actor, actor[i].src_rect, actor[i].dst_rect); - - // Pintem el marcador - DrawHud(); - - // Posem el filtro de pantalla - if prog.filter then - begin - SDL_RenderSetLogicalSize(renderer, 640, 480); - DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); - end; - - // Mostrem la pantalla - SDL_RenderPresent(renderer); - - delta_time := SDL_GetTicks(); - end; - end; - end; - - SECTION_MENU: - begin - // Establir el color d'esborrat - SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); - - // Apaga la musica - Mix_HaltMusic(); - - while menu.enabled do - begin - // Bucle del menu - while SDL_PollEvent(@e) > 0 do - begin - // Si arriva el event de tancar la aplicació, eixim del bucle - if (e.type_ = SDL_QUITEV) then - begin - quit := true; - menu.enabled := FALSE; - break; - end - else - if ((e.type_ = SDL_KEYDOWN) and (e.key._repeat = 0)) then - case e.key.keysym.scancode of - SDL_SCANCODE_ESCAPE: - begin - quit := true; - SetProgSection(SECTION_QUIT); - break; - end; - - // (Des)Activa el mode de pantalla completa - SDL_SCANCODE_F: - begin - if ( fullscreen ) then - begin - SDL_SetWindowFullscreen(window, 0); - SDL_ShowCursor(1); - fullscreen := false; - end - else - begin - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); - SDL_ShowCursor(0); - fullscreen := true; - end; - end; - - // (Des)Activa la musica - SDL_SCANCODE_M: - begin - prog.music_enabled := not(prog.music_enabled); - if (prog.music_enabled) then - Mix_VolumeMusic(100) - else - Mix_VolumeMusic(0); - end; - - // (Des)Activa les scanlines - SDL_SCANCODE_F2: - begin - prog.filter := not(prog.filter); - end; - - // Inicia el joc - SDL_SCANCODE_RETURN: - begin - if (menu.timer > 99) then - begin - menu.timer := 99; - Mix_HaltMusic(); - Mix_HaltChannel(-1); - Mix_PlayChannel(-1, menu.sound_start, 0); - menu.frame := 0; - end; - end; - end; - end; - - if ((SDL_GetTicks() - delta_time) > GAME_SPEED) then - begin - case menu.section of - {MENU_SECTION_MAIN: - begin - if menu.timer > 100 then - // Menu normal - begin - menu.frame := (menu.frame + 1) mod 30000; - - SDL_RenderSetLogicalSize(renderer, 320, 240); - // Borrem pantalla - SDL_RenderClear(renderer); - - // Pintem el fondo del menu - //DrawSprite(menu.sprite, menu.src_rect_fondo, menu.dst_rect_fondo); - - // Pintem el logo DESPLEGA - menu.dst_rect_logo_zoom.w := menu.dst_rect_logo.w; - menu.dst_rect_logo_zoom.h := min(menu.dst_rect_logo_zoom.h + 4, menu.dst_rect_logo.h); - menu.dst_rect_logo_zoom.x := menu.dst_rect_logo.x; - menu.dst_rect_logo_zoom.y := menu.dst_rect_logo.y; - - DrawSprite(menu.sprite, menu.src_rect_logo, menu.dst_rect_logo_zoom); - - if menu.frame = (154 div 4) then - Mix_PlayChannel(-1, menu.sound_logo, 0); - if menu.frame = (300 div 4) then - // Conecta la musica - Mix_PlayMusic(menu.music, -1); - - if menu.frame > (300 div 4) then - begin - // Pintem el text: PRESS RETURN TO START - if ((menu.frame mod 64) < 32) then - DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); - - // Pintem el text: JAILGAMES 2016 - DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); - end; - end - else - // Menu havent apretat START/RETURN - begin - dec(menu.timer); - menu.frame := (menu.frame + 1) mod 30000; - - // Borrem pantalla - SDL_RenderSetLogicalSize(renderer, 320, 240); - SDL_RenderClear(renderer); - - // Pintem el fondo del menu - //DrawSprite(menu.sprite, menu.src_rect_fondo, menu.dst_rect_fondo); - - // Pintem el logo - DrawSprite(menu.sprite, menu.src_rect_logo, menu.dst_rect_logo); - - // Pintem el text: PRESS RETURN TO START - if ((menu.frame mod 8) < 4) then - DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); - - // Pintem el text: JAILGAMES 2016 - DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); - - if menu.timer = 0 then - begin - //prog.section := SECTION_GAME; - //menu.enabled := FALSE; - //game.enabled := TRUE; - //menu.section := MENU_SECTION_ANIMATION; - //menu.timer := 100 - end; - end; - - // Posem el filtro de pantalla - if prog.filter then - begin - SDL_RenderSetLogicalSize(renderer, 640, 480); - DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); - end; - - // Mostrem la pantalla - SDL_RenderPresent(renderer); - - delta_time := SDL_GetTicks(); - end;} - - MENU_SECTION_ANIMATION: - begin - // No hem pulsat el botó d'start - if menu.timer > 100 then - // Animació inicial - if not(menu.animation[0].loops) then - begin - // Borrem pantalla - SDL_RenderSetLogicalSize(renderer, 320, 240); - SDL_RenderClear(renderer); - - AnimateIntroMenu(menu.animation[0], menu.src_rect_animation); - - // Pintem la animacio - DrawSprite(menu.sprite_animation, menu.src_rect_animation, menu.dst_rect_animation); - - // Posem el filtro de pantalla - if prog.filter then - begin - SDL_RenderSetLogicalSize(renderer, 640, 480); - DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); - end; - - // Mostrem la pantalla - SDL_RenderPresent(renderer); - - delta_time := SDL_GetTicks(); - end - else - // Animació segona en loop - begin - if Mix_PlayingMusic() = 0 then - Mix_PlayMusic(menu.music, -1); - - // Borrem pantalla - SDL_RenderSetLogicalSize(renderer, 320, 240); - SDL_RenderClear(renderer); - - AnimateIntroMenu(menu.animation[1], menu.src_rect_animation); - - // Pintem la animacio - DrawSprite(menu.sprite_animation, menu.src_rect_animation, menu.dst_rect_animation); - - // Pintem el text: PRESS RETURN TO START - if ((menu.animation[1].timer mod 64) < 32) then - DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); - - // Pintem el text: JAILGAMES 2016 - DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); - - // Posem el filtro de pantalla - if prog.filter then - begin - SDL_RenderSetLogicalSize(renderer, 640, 480); - DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); - end; - - // Mostrem la pantalla - SDL_RenderPresent(renderer); - - delta_time := SDL_GetTicks(); - end - else - // Hem pulsat el botó d'start - begin - Mix_HaltMusic(); - - // Borrem pantalla - SDL_RenderSetLogicalSize(renderer, 320, 240); - SDL_RenderClear(renderer); - - AnimateIntroMenu(menu.animation[1], menu.src_rect_animation); - - // Pintem la animacio - DrawSprite(menu.sprite_animation, menu.src_rect_animation, menu.dst_rect_animation); - - // Pintem el text: PRESS RETURN TO START - if ((menu.animation[1].timer mod 8) < 4) then - DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); - - // Pintem el text: JAILGAMES 2016 - DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); - - // Posem el filtro de pantalla - if prog.filter then - begin - SDL_RenderSetLogicalSize(renderer, 640, 480); - DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); - end; - - // Mostrem la pantalla - SDL_RenderPresent(renderer); - - delta_time := SDL_GetTicks(); - - dec(menu.timer); - if menu.timer = 0 then - begin - SetProgSection(SECTION_GAME); - menu.timer := 200; - end; - end; - end; - end; - end; - end; - end; - end; - end; - - // Finalitzar la música, els samples i el audio - CloseSound(player.sound_jump); - CloseSound(player.sound_death); - CloseSound(player.sound_coin); - CloseSound(menu.sound_logo); - CloseSound(menu.sound_start); - CloseSound(game.sound_drop_enemy); - CloseSound(game.sound_drop_splat); - - Mix_HaltMusic(); - - CloseMusic(game.music); - CloseMusic(menu.music); - - Mix_CloseAudio(); - - EndProgram(); - - // Finalitzar SDL_Image - IMG_Quit(); - - // Destruir els sprites - ClosePicture(prog.sprite); - ClosePicture(player.sprite); - ClosePicture(map.sprite_tile); - ClosePicture(map.sprite_actor); - ClosePicture(map.background); - ClosePicture(menu.sprite); - ClosePicture(menu.sprite_animation); - ClosePicture(hud.sprite); - - // Destruir la finestra - SDL_DestroyWindow(window); - - // Finalitzar SDL - SDL_Quit(); -end. diff --git a/sync.sh b/sync.sh index b117b10..8970ae0 100755 --- a/sync.sh +++ b/sync.sh @@ -1,4 +1,6 @@ #!/bin/bash +readonly PROJECT=volcano + readonly USAGE=" USAGE: $(basename "$0") [UPLOAD or DOWNLOAD]" @@ -23,12 +25,12 @@ fi # UPLOAD if [ "$1" = upload ] || [ "$1" = UPLOAD ]; then - printf "\n%s\n" "uploading volcano" - rsync -azmPu --delete -e 'ssh -p 4545' . sergio@sustancia.synology.me:/home/sergio/backup/code/volcano/ - rsync -azmPu -e 'ssh -p 4545' . sergio@sustancia.synology.me:/home/sergio/backup/code/volcano.all/ + printf "\n%s\n" "uploading $PROJECT" + rsync -azmPu --delete -e 'ssh -p 4545' . sergio@sustancia.synology.me:/home/sergio/backup/code/$PROJECT/ + rsync -azmPu -e 'ssh -p 4545' . sergio@sustancia.synology.me:/home/sergio/backup/code/$PROJECT.all/ fi if [ "$1" = download ] || [ "$1" = DOWNLOAD ]; then - printf "%s\n" "downloading volcano" - rsync -azmP --delete -e 'ssh -p 4545' sergio@sustancia.synology.me:/home/sergio/backup/code/volcano/* . + printf "%s\n" "downloading $PROJECT" + rsync -azmP --delete -e 'ssh -p 4545' sergio@sustancia.synology.me:/home/sergio/backup/code/$PROJECT/* . fi \ No newline at end of file