Transferred from GitHub

This commit is contained in:
Maddox Werts 2024-05-08 13:37:48 -04:00
parent b3307ea298
commit 22800bbd23
60 changed files with 2450 additions and 2 deletions

29
Makefile Normal file
View file

@ -0,0 +1,29 @@
# THIS IS THE MAKE FILE FOR TURNING
# ALL C FILES INTO BINARIES
# VARIABLES
LIBS = -lsdl2main -lsdl2_ttf -lsdl2_image -lsdl2_mixer -lsdl2
# COMPILING
all: CLS compile link install clean
CLS:
clear
compile:
gcc -c -I inc src/app/*.c
gcc -c -I inc src/gme/*.c
gcc -c -I inc src/scn/*.c
gcc -c -I inc src/*.c
link:
gcc *.o -L lib $(LIBS) -o bin/blokos
install:
cp -vr res bin
clean:
rm *.o
run:
./bin/blokos

View file

@ -1,3 +1,66 @@
# Blokos
# BLOKOS #
### By Maddox Werts. ###
Tetris in C
## What is this? ##
This is a simple Computer Science project I'll be working on
for the following 5 days as instructed. This project is using
the C language, so code will make more sense in this.
Also, To pronounce it, it's BLOCK * OU * SS
## Why not C++? ##
I wanted to challange myself, I'm going to use C because
it's an older language, and one of the Most popular.
## How can I play BLOKOS? ##
There will be Two methods!
- [Downloading from the Releases Page](https://github.com/Maddox-Werts/Blokos/releases)
- [Compiling it yourself](#compiling)
## Will this recieve Updates? ##
Possibly, I may port this to
- Nintendo Switch with LIBNX by the DevkitPro team.
- Nintendo 3DS with LIB3DS by the DevkitPro team.
- Xbox ( Original ) with the open source XDK from the community.
- Android/iOS with some SDK's here and there.
## If I'm programming for BLOKOS, What references can I have? ##
I HIGHLY recommend using this resource to help you
- [Tetris, Tetrimino Guide](https://tetris.fandom.com/wiki/Tetromino)
- [Tetris, Scoring Guide](https://tetris.wiki/Scoring)
- [Tetris, Free Online](https://bit.ly/3z0jaOl)
# Compiling #
You'll just need a few things. I'm not including ANY libraries
such as __SDL2__, __SDL2 TTF Support__. You'll need to download those from the
[DOWNLOADS](#downloads) section.
First, Use these commands to Clone, CD and Make the project
```bash
git clone https://github.com/Maddox-Werts/Blokos.git
cd Blokos
make
```
And that's it! Make sure you have the said libraries though!
Insinde my **MAKEFILE** I have it so that it automatically
launches the binaries. HOWEVER, If you're on windows, you will
manually need to insert the dll files if you're on windows.
### DLL FILES REQUIRED TO LAUNCH ON WINDOWS ###
- SDL2.dll
- SDL2_ttf.dll
- SDL2_image.dll
- zlib1.dll
- libpng16-16.dll
# Downloads #
### TOOLS ###
- [MINGW](https://sourceforge.net/projects/mingw/)
- [SDL2](http://libsdl.org/download-2.0.php)
- [SDL2 TTF](https://github.com/libsdl-org/SDL_ttf/releases/tag/release-2.0.18)
- [SDL2 Image](https://www.libsdl.org/projects/SDL_image)
- [SDL2 Mixer](http://libsdl.org/projects/SDL_mixer)
### IDE's ( Up to you ) ###
- [Visual Studio Code](https://code.visualstudio.com/)

1
art/Cell.piskel Normal file
View file

@ -0,0 +1 @@
{"modelVersion":2,"piskel":{"name":"Cell","description":"","fps":12,"height":16,"width":16,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKklEQVQ4T2O8ffv2fwYKAOOoAQyjYcAwLMLgxo0blOWFgTfg5MmTFHkBAH65OMAeVamsAAAAAElFTkSuQmCC\"}]}","{\"name\":\"Layer 3\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAbElEQVQ4T2NkoBAwgvTPnz//v5ycHIO2tjbRxj169IjBzMyMEWzA3r17//Py8oIFiDXh1KlT/+EGvHjx4r+EhATRmkGWjBowGgYDnw5AqfDz588Mzs7OkLwAEiA2D4DUgTSDMlNiYiLEAEoAAPi3dBElyQj0AAAAAElFTkSuQmCC\"}]}","{\"name\":\"Layer 2\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAK0lEQVQ4T2NkYGD4D8RkA0aoASCaHPB/1ACG0TAAJsLRdEDFMCAnJ4L1AAAJ8x4Bn3F+MgAAAABJRU5ErkJggg==\"}]}"],"hiddenFrames":[""]}}

1
art/Monster.piskel Normal file
View file

@ -0,0 +1 @@
{"modelVersion":2,"piskel":{"name":"Monster","description":"","fps":6,"height":16,"width":16,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAIElEQVQ4T2MUDmL4z0ABYBw1gGE0DBhGwwCYh4ZBOgAA40kWUQ8UUdcAAAAASUVORK5CYII=\"}]}","{\"name\":\"Layer 4\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAnUlEQVQ4T6VTywqAMAzbwKv4MV78/9Mufox4FSYdVLr0MUWPtkmTtMvp55cj/LylepbU9dA/xlDtKXKBAdgoB0lixY4TLYXLOtVjvxo2tEANqASVmv4sFVK2JOkyIKCVRWRLEWBYMnG2JAkbAU61gvO2okJkr29IzS14YaEq7vu0BSLBoN07iLYxvETLv5eJegss09sE3sTwlEev/QaDJG0Rgk0iTAAAAABJRU5ErkJggg==\"}]}","{\"name\":\"Layer 3\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAv0lEQVQ4T2NkoBAwkqP/PwPDf6BGsF6SDUDWjGHAJ6DJIEE+PAbD1MDUgV3wCqhRDKgJRMO8BOIT4z24ottAzapEakI2GKctx5FcA9JgicNwnAZsAxrgBdWEzAYZBuKDaJA82IDlaLZFotkGkoeJwdTC+HAXzIEakkJEOIDUwtQRFdLIgdYJ1FyOZAmKAelAyZlEuABrLLiihQNM0W4kA9HVgOTgLjAEGnAeqhjEBhkA46MnKGS1JIcBumEUGwAASiwuEVvSVUcAAAAASUVORK5CYII=\"}]}","{\"name\":\"Layer 5\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAATklEQVQ4T2NkoBAwUqifgfoG9P/P/V/IOJlog4lWiOxVZEvIMgDZMOoYgO5vUsKBOi4glBbwuYg+LsDmQpirMFxASgCCDB44L8C8RbELAJM4HBFmjLSWAAAAAElFTkSuQmCC\"}]}","{\"name\":\"Layer 6\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAiElEQVQ4T2NkoBAwUqifYbga8B8IsIUNIxCgi2MIgDQfOnSIwc7OjoFBXp6B4eFDMH1o8WKwGLohKAaga1b+8AFs4d2PH3EaAjcAphmkwS42FmyzMj8/gybQ1VuANIgPchlYHskleF3gA7IZCMAGAAE2bxAOA5BOqO0EwwAWwhTFAqlJexgkZQAJO0sRcMA8UgAAAABJRU5ErkJggg==\"}]}","{\"name\":\"Layer 2\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAK0lEQVQ4T2NkYGD4D8RkA0aoASCaHPB/1ACG0TAAJsLRdEDFMCAnJ4L1AAAJ8x4Bn3F+MgAAAABJRU5ErkJggg==\"}]}"],"hiddenFrames":[null]}}

1
art/PrimaxLogo.piskel Normal file
View file

@ -0,0 +1 @@
{"modelVersion":2,"piskel":{"name":"PrimaxLogo","description":"","fps":12,"height":32,"width":32,"layers":["{\"name\":\"Layer 1\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAXUlEQVRYR+2XMQ4AIAjE5P+P1jhgRIkb4FAf4NVOVlrxkeL95gH0YCizeQJEj+vb1u4OkDVuIADAAAYwgAEMYAADGMAABr4yMP/rWW3ghokGQzTEM82Cs/C+vryOB4G4HCFvqmLqAAAAAElFTkSuQmCC\"}]}","{\"name\":\"Layer 6\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAjklEQVRYR+2UsREAIQgEsQ17sA5zm7AOyrAUq/PnAhz+51M0ORIxunVhTHK50uV8CQXova9aq8w5BSeqtfbKDAfIOUspZYsGzBhj54YCIFVVFwC8BW8iHABjMAt/owgHwGs9BO5+DEcAPAR6jMSW8RiAbSFsoLdFPA7w/XcIQAM0QAM0QAM0QAM0QAM08ACUESshdcGWIQAAAABJRU5ErkJggg==\"}]}","{\"name\":\"Layer 2\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAs0lEQVRYR2NkGGDAOMD2M4w6AG8IfIrT/I8cRXyLrlM9xHAaCLKcU1CEgXXiYbCa3/m2/7+/f8NAbUdgdQC65bBQoIUjcDoAl09BjqNmKAxeB7z8/I1Bdf1DFAfeDpT/L87LRdV0gDMEQPGO7AhaWA6yA68D0EtJasY9zGy8DqCFheieGnXAaAiMhsBoCIyGwOAMAVrVfNi6ADjbhCBHoLcHaNGHoHorl1RHjjpgNAQGPAQAUip8IYhG4nEAAAAASUVORK5CYII=\"}]}","{\"name\":\"Layer 5\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAATElEQVRYR2NkGGDAOMD2M4w6YDQEBn8I3Dzk9R+UU9TtttHEsQQNHXAH0LqcIBgCow4YDYHREBgNgdEQGA2B0RAYDYHREBgNgWEfAgC+LgghYMhGZAAAAABJRU5ErkJggg==\"}]}","{\"name\":\"Layer 3\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAsElEQVRYR2NkGGDAOMD2M4w6YDQERkNgNARGQ2BohMCLloT/sDpDomYBI4iPTIPkYGK42MjyyPUPUSEA0nzqwQuwPr85Oxg3pXj8B9HIDgPJwRwFUmumIAHmg9SC2CAxkB70yo9oB4AMg2lGDgGYw2AWoocWeohQ3QEwh6E7CuagAXEAejpBjhKyQgAW5zDNMD6yOLoYLj5ZDqBlq4moRDjqgNEQGA2B0RAYDYFhHQIA1LuqIbKxb6QAAAAASUVORK5CYII=\"}]}","{\"name\":\"Layer 4\",\"opacity\":1,\"frameCount\":1,\"chunks\":[{\"layout\":[[0]],\"base64PNG\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvUlEQVRYR2NkGGDAOMD2M4w6YDQERkNgNARGQ2A0BEZDYDQERkOAqBB40ZLwH9Z0k6hZQJQeYpt6RBkGcsCpBy/AZvrN2cEIcxDMMch8EBskjk8NsuOIdgByCKCHCLJlm1I8/iM7EqQPm4Ng5hHtAPQQAPHNFCTAhoMshbGRQwBZDSwUQY6jSgjAfIXuO2QH4FJDsgNAPoRpAvkAFszINCx9YJOD6YGpIdkBxKZoctQRlQbIMZhYPaMOGA0BAHn9myFundDUAAAAAElFTkSuQmCC\"}]}"],"hiddenFrames":[""]}}

4
bin/README.MD Normal file
View file

@ -0,0 +1,4 @@
# The BINARY FOLDER #
This folder will contain the executables you'll need to compile if
you're not downloading from the Releases Tab!

View file

@ -0,0 +1,2 @@
Just toss the downloaded SDL Includes in this folder
(Blokos/inc)

View file

@ -0,0 +1,2 @@
Just toss the downloaded SDL Library ( MINGW i686 ) in this folder
(Blokos/inc)

BIN
res/fonts/default.ttf Normal file

Binary file not shown.

3
res/prefs.conf Normal file
View file

@ -0,0 +1,3 @@
# This file will hold the user's preferences!
width=512
height=512

5
res/saves/save.conf Normal file
View file

@ -0,0 +1,5 @@
# This is a default save file.
# Everything beginning with the # will become a comment
time_alive=0
high_score=0
names=none

BIN
res/sounds/clear.wav Normal file

Binary file not shown.

BIN
res/sounds/die.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
res/sounds/misc/chip.wav Normal file

Binary file not shown.

BIN
res/sounds/misc/coin.wav Normal file

Binary file not shown.

BIN
res/sounds/primaxding.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
res/sprites/cell.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

BIN
res/sprites/monster.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

BIN
res/sprites/primax.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

BIN
res/sprites/title.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

17
src/app/dtime.c Normal file
View file

@ -0,0 +1,17 @@
// Files
// --SYSTEM
#include <stdio.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "dtime.h"
// Functions
void updateTime(){
// Time details
LAST = NOW;
NOW = SDL_GetPerformanceCounter();
// Getting DT
deltatime = (float)( (NOW - LAST) * 100 / (float)SDL_GetPerformanceFrequency() );
}

19
src/app/dtime.h Normal file
View file

@ -0,0 +1,19 @@
// Define once
#ifndef H_DTIME
#define H_DTIME
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// Variables
Uint64 NOW, LAST;
float deltatime;
// Functions
void updateTime();
// End definition
#endif

8
src/app/features.c Normal file
View file

@ -0,0 +1,8 @@
// Files
// --HEADERS
#include "features.h"
// Functions
float Lerp(float a, float b, float t){
return a + t * (b - a);
}

11
src/app/features.h Normal file
View file

@ -0,0 +1,11 @@
// Define once
#ifndef H_FEATURES
#define H_FEATURES
// Files
// Functions
float Lerp(float a, float b, float t);
// End definition
#endif

72
src/app/prefs.c Normal file
View file

@ -0,0 +1,72 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// --HEADERS
#include "prefs.h"
// Functions
PX_PrefrenceResult px_ReadPrefs(){
// Variables
PX_PrefrenceResult holder;
FILE* file;
char line[512];
// Loading the file
file = fopen("res/prefs.conf", "r");
// Was the file loaded
if(file == NULL){
printf("FAILED TO OPEN PREFS FILE!\n");
}
// Reading contents
while(fgets(line, 512, file) != NULL){
if(line[0] == '#'){ // This is a comment
}
else{
// Variables
char* args = (char*)malloc(3 * sizeof(int));
// Getting stuff
strcpy(args, strtok(line, "="));
// Holders
char* name;
char* value;
int time = 0;
// What was the thing?
while(args != NULL){
if(time == 0){
name = args;
}
else{
value = args;
}
args = strtok(NULL, "=");
time += 1;
}
if(strcmp(name, "width") == 0){
holder.width = atoi(value);
}
else if(strcmp(name, "height") == 0){
holder.height = atoi(value);
}
// Clean
free(args);
}
}
// Cleanup
fclose(file);
// return
return holder;
}

18
src/app/prefs.h Normal file
View file

@ -0,0 +1,18 @@
// Define once
#ifndef H_PREFS
#define H_PREFS
// Files
// --SYSTEM
// --HEADERS
// Structures
typedef struct PX_PrefrenceResult{
int width, height;
} PX_PrefrenceResult;
// Functions
PX_PrefrenceResult px_ReadPrefs();
// End definition
#endif

34
src/app/renderer.c Normal file
View file

@ -0,0 +1,34 @@
// Files
// --SYSTEM
#include <stdio.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "renderer.h"
// Functions
SDL_Renderer* px_RendererCreate(SDL_Window* window){
// Making a renderer from the window
SDL_Renderer* renderer = SDL_CreateRenderer(
window, 0, SDL_RENDERER_ACCELERATED
);
// Was the renderer made?
if(renderer == NULL){
printf("Failed to create renderer!\n");
}
return renderer;
}
void px_RendererDelete(SDL_Renderer* renderer){
SDL_DestroyRenderer(renderer);
free(renderer);
}
void px_RendererClear(SDL_Renderer* renderer){
SDL_SetRenderDrawColor(renderer, 0,0,0, 1);
SDL_RenderClear(renderer);
}
void px_RendererDisplay(SDL_Renderer* renderer){
SDL_RenderPresent(renderer);
}

19
src/app/renderer.h Normal file
View file

@ -0,0 +1,19 @@
// Define Once
#ifndef H_RENDERER
#define H_RENDERER
// Files
// --SYSTEM
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
// Functions
SDL_Renderer* px_RendererCreate(SDL_Window* window);
void px_RendererDelete(SDL_Renderer* renderer);
void px_RendererClear(SDL_Renderer* renderer);
void px_RendererDisplay(SDL_Renderer* renderer);
// End definition
#endif

154
src/app/saves.c Normal file
View file

@ -0,0 +1,154 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// --HEADER
#include "saves.h"
// Functions
PX_SaveGame px_saveRead(const char* fileName){
// Holder
PX_SaveGame saveGame;
// Variables
FILE* savefile;
char line[512];
printf("Reading save from: \n%s\n", fileName);
// Loading from file
savefile = fopen(fileName, "r");
// Was the file opened?
if(savefile == NULL){
printf("Failed to open %s.\n", fileName);
}
else{
printf("Successfully read.\n");
}
// Loading each line
while(fgets(line, 512, savefile) != NULL){
// Checking if it's a comment
if(!(line[0] == '#')){
// Getting the following arguments
//char* saveargs = (char*)malloc(4 * sizeof(int));
char* saveargs;
// Split the line
//strcpy(saveargs, line);
saveargs = strtok(line, "=");
// Temporary Variables
char* savename;
char* savevalue;
// What are our arguments?
savename = saveargs;
saveargs = strtok(NULL, "=");
savevalue = saveargs;
printf("Loaded info:\n Name: %s\n Value: %s\n\n", savename, savevalue);
// What was the name?
if(strcmp(savename, "high_score") == 0){
saveGame.high_score = atoi(savevalue);
printf("Saved high score as: %i\n", saveGame.high_score);
}
if(strcmp(savename, "time_alive") == 0){
saveGame.time_alive = atoi(savevalue);
printf("Saved time alive as: %i\n", saveGame.time_alive);
}
}
}
// Cleanup
fclose(savefile);
// Returning
return saveGame;
}
void px_saveWrite(const char* filename, const char* name, const char* value){
// DEBUG
printf("Writing to saves..\n");
// What's the path?
char* path = (char*)malloc(5 * sizeof(int));
strcpy(path, "res/saves/");
strcat(path, filename);
char* tpath = (char*)malloc(5 * sizeof(int));
strcpy(tpath, path);
strcat(tpath, ".tmp");
printf("Paths: %s, %s\n", path, tpath);
// DEBUG
printf("Got both save paths..\n");
// Getting the file
FILE* savefile = fopen(path, "r");
FILE* newfile = fopen(tpath, "w");
// DEBUG
printf("Loaded both files.\nOG: %i\n NEW: %i\n", (int)(savefile == NULL), (int)(newfile == NULL));
// Variables
char line[512];
// For each of the lines
while(fgets(line, 512, savefile) != NULL){
// Is the line a comment?
if(line[0] != '#'){
// Check the arguments
char* saveargs = (char*)malloc(4 * sizeof(int));
strcpy(saveargs, strtok(line, "="));
// Is this what we want?
// Writing!
char* result = (char*)malloc(4 * sizeof(int));
strcpy(result, saveargs);
strcat(result, "=");
if(strcmp(saveargs, name) == 0){
strcat(result, value);
}
else{
strcpy(result, line);
strcat(result, "=");
strcat(result, strtok(NULL, "\n"));
}
printf("Result: %s\n", result);
// Override line
fputs(result, newfile);
fputc('\n', newfile);
// Cleanup
free(result);
// Cleanup
free(saveargs);
}
else{
// Write to file
fputs(line, newfile);
}
}
// Closing files
fclose(savefile);
fclose(newfile);
// Remove the original
remove(path);
// Override
rename(tpath, path);
return;
}

21
src/app/saves.h Normal file
View file

@ -0,0 +1,21 @@
// Define once
#ifndef H_SAVES
#define H_SAVES
// Files
// --SYSTEM
#include <stdio.h>
// --HEADERS
// Structures
typedef struct PX_SaveGame{
int high_score;
int time_alive;
} PX_SaveGame;
// Functions
PX_SaveGame px_saveRead(const char* fileName);
void px_saveWrite(const char* filename, const char* name, const char* value);
// End definition
#endif

90
src/app/sound.c Normal file
View file

@ -0,0 +1,90 @@
// Files
// --SYSTEM
#include <stdio.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
// --HEADERS
#include "sound.h"
// Variables
int totalSounds = 0;
// Functions
void px_SoundStart(){
// Values
const Uint16 a_format = AUDIO_S16SYS;
const int a_rate = 22050;
const int a_channels = 2;
const int a_buffers = 4096;
// Opening a sound
if((Mix_OpenAudio(a_rate, a_format, a_channels, a_buffers))){
printf("Failed to load Audio Systems!\n");
}
else{
printf("Audio Systems started successfuly!\n");
}
}
void px_SoundPlay(const char* file, int type){
// Holding
Mix_Chunk* chnk;
// Freeing previous sound
switch(type){
case 0: // Background Sounds
Mix_FreeChunk(backgroundsound);
break;
case 1: // Player Sounds
Mix_FreeChunk(playersound);
break;
case 2: // Entity Sounds
Mix_FreeChunk(entitysound);
break;
}
// Getting the audio file
Mix_Chunk* tchunk = Mix_LoadWAV(file);
if(!tchunk){
printf("Failed to load Audio File!\n");
return;
}
// Setting the current sound
switch(type){
case 0: // Background Sounds
backgroundsound = tchunk;
// Playing the sound
if(!backgroundsound){
printf("The current sound does not exist!\n");
return;
}
Mix_PlayChannel(-1, backgroundsound, 0);
break;
case 1: // Player Sounds
playersound = tchunk;
// Playing the sound
if(!playersound){
printf("The current sound does not exist!\n");
return;
}
Mix_PlayChannel(-1, playersound, 0);
break;
case 2: // Entity Sounds
entitysound = tchunk;
// Playing the sound
if(!entitysound){
printf("The current sound does not exist!\n");
return;
}
Mix_PlayChannel(-1, entitysound, 0);
break;
}
}

22
src/app/sound.h Normal file
View file

@ -0,0 +1,22 @@
// Define Once
#ifndef H_SOUND
#define H_SOUND
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL2
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
// Variables
Mix_Chunk* backgroundsound;
Mix_Chunk* playersound;
Mix_Chunk* entitysound;
// Functions
void px_SoundStart();
void px_SoundPlay(const char* file, int type);
// End definition
#endif

67
src/app/text.c Normal file
View file

@ -0,0 +1,67 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
// --HEADERS
#include "text.h"
// Functions
PX_Text px_TextCreate(SDL_Renderer* renderer, const char* msg){
// Starting TTF system
TTF_Init();
// Making the holding structure
PX_Text holdtext;
// Holders/Helpers
SDL_Surface* surf;
SDL_Texture* text;
TTF_Font* font;
// Was the font opened?
if(!(font = TTF_OpenFont("res/fonts/default.ttf", 16))){
printf("Could not open font!\n");
}
// Getting a color
SDL_Color txt_color = {
255,255,255, 255
};
// DEBUG
printf("Your message: %s.\n", msg);
if( !(surf = TTF_RenderText_Solid(font, msg, txt_color)) ){
printf("Failed to create Render Text\n");
}
if( !(text = SDL_CreateTextureFromSurface(renderer, surf)) ){
printf("Failed to create Render Text Texture\n");
}
// Assigning stuff
holdtext.font = font;
holdtext.surface = surf;
holdtext.texture = text;
holdtext.width = surf->w;
// Giving result
return holdtext;
}
void px_TextDraw(SDL_Renderer* renderer, PX_Text text, int x, int y, int w, int h){
// Holding variable
SDL_Rect rect;
// Color
SDL_SetRenderDrawColor(renderer, 0,0,0, 1);
// Giving rect stuff
rect.x = x; rect.y = y;
rect.w = w; rect.h = h;
// Rendering
SDL_RenderDrawRect(renderer, &rect);
SDL_RenderCopy(renderer, text.texture, NULL, &rect);
}

26
src/app/text.h Normal file
View file

@ -0,0 +1,26 @@
// Define once
#ifndef H_TEXT
#define H_TEXT
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
// Structures
typedef struct PX_Text{
TTF_Font* font;
SDL_Surface* surface;
SDL_Texture* texture;
int width;
} PX_Text;
// Functions
PX_Text px_TextCreate(SDL_Renderer* renderer, const char* msg);
void px_TextDraw(SDL_Renderer* renderer, PX_Text text, int x, int y, int w, int h);
// End if
#endif

31
src/app/texture.c Normal file
View file

@ -0,0 +1,31 @@
// Files
// --SYSTEM
#include <stdio.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// --HEADERS
#include "texture.h"
// Functions
SDL_Texture* px_TextureCreate(SDL_Renderer* renderer, const char* file){
// Helpers
SDL_Texture* result;
SDL_Surface* texsurf;
// Was the surface loaded?
if(!(texsurf = IMG_Load(file))){
printf("Failed to load Texture Image: %s.\n", file);
}
// Converting surface to texture
if(!(result = SDL_CreateTextureFromSurface(renderer, texsurf))){
printf("Failed to create texture from surface!\n");
}
// Cleanup
SDL_FreeSurface(texsurf);
// Returning Result
return result;
}

14
src/app/texture.h Normal file
View file

@ -0,0 +1,14 @@
// Defining
#ifndef H_TEXTURE
#define H_TEXTURE
// Files
// --SYSTEM
// --SDL
#include <SDL2/SDL.h>
// Functions
SDL_Texture* px_TextureCreate(SDL_Renderer* renderer, const char* file);
// End definition
#endif

67
src/app/window.c Normal file
View file

@ -0,0 +1,67 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "window.h"
/*
-- THIS IS FOR THE WINDOW! --
*/
// Functions
PX_Window px_WindowCreate(const char* title, int width, int height){
// Starting some things
SDL_Init(SDL_INIT_VIDEO);
SDL_Init(SDL_INIT_AUDIO);
// Making the holding structure
PX_Window window;
// Creating a window
window.window = SDL_CreateWindow(
title,
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_SHOWN
);
// Was the window created?
if(window.window == NULL){
printf("Failed to create window!\n");
}
// Setting others
window.width = width;
window.height = height;
window.opened = true;
// Returning Window
return window;
}
void px_WindowDelete(PX_Window* window){
SDL_DestroyWindow(window->window);
free(window);
}
void px_WindowUpdate(PX_Window* window){
// Making an event holder
SDL_Event ev;
// Polling through events
while(SDL_PollEvent(&ev)){
// Going through all types
switch(ev.type){
// Pressing the X button
case SDL_QUIT:
window->opened = false;
break;
// Pressing Escape
case SDL_KEYDOWN:
if(ev.key.keysym.scancode == SDL_SCANCODE_ESCAPE) { window->opened = false; }
break;
}
}
}

26
src/app/window.h Normal file
View file

@ -0,0 +1,26 @@
// Define once
#ifndef H_WINDOW
#define H_WINDOW
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
// Structures
typedef struct PX_Window{
SDL_Window* window;
int width, height;
bool opened;
} PX_Window;
// Functions
PX_Window px_WindowCreate(const char* title, int width, int height);
void px_WindowDelete(PX_Window* window);
void px_WindowUpdate(PX_Window* window);
// End definition
#endif

250
src/gme/monster.c Normal file
View file

@ -0,0 +1,250 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// --HEADERS
#include "../gme/scene.h"
#include "../app/sound.h"
#include "../app/dtime.h"
#include "monster.h"
// Constants
#define FALLT 4
#define RESPAWNT 213
#define FALLSLICE 120.0f/1000.0f
// Variables
bool finishedAnger = false;
float ftime = 0;
int standstill = 0;
// Functions
// --HELPER
void px_MACTIVATE(PX_Monster* monster){
// Adding to time
if(ftime > RESPAWNT){
ftime = 0;
standstill = false;
monster->active = true;
monster->x = 3;
monster->y = 0;
// Making the sounds
px_SoundPlay("res/sounds/entities/anger.wav", 2);
}
else{
ftime += deltatime * FALLSLICE;
}
}
void px_MFALL(PX_Monster* monster, PX_Scene* scene){
// Grounded?
if(monster->grounded) {return;}
// Falling
if(ftime > FALLT){
monster->y += 1;
ftime = 0;
}
// Counting
else{
ftime += deltatime * FALLSLICE;
}
// Are we below the grid?
if(monster->y > GRIDY){
monster->active = false;
return;
}
}
void px_MSTRIDE(PX_Monster* monster, PX_Scene* scene){
// Can we even move?
if(ftime < FALLT){
return;
}
// Getting a random direction
srand(time(NULL));
// Helpers
int randec, direction;
// Getting the random range
randec = rand() % 100;
// Here's whats gonna happen:
/*
IF: The range is between 0-40
THEN: Move LEFT
IF: the range is between 40-60
THEN: Stay put
IF: the range is between 60-100
THEN: Move RIGHT
*/
if(randec < 40){
direction = -1;
}
else if(40 <= randec && randec <= 60){
return;
}
else if(60 < randec && randec < 100){
direction = +1;
}
else{
printf("What did you do? It's broken?\n");
}
// Can we move in the direction we want?
if(monster->x + direction < 0){
monster->x = GRIDX - 1;
}
else if(monster->x + direction > GRIDX - 1){
monster->x = 1;
}
// Will we end up moving into a tile?
int nexttile = px_SceneGet(scene, monster->x + direction, monster->y);
if(nexttile != 0) {standstill += 1; return;}
else {standstill = 0;}
monster->x += direction;
// Sounds
px_SoundPlay("res/sounds/entities/move.wav", 2);
}
void px_MKILL(PX_Monster* monster, PX_Scene* scene){
/*
We won't kill the monster if he is overriden by a block
that is already placed
===========================
*/
// What's our position in the grid?
int ccell = px_SceneGet(scene, monster->x, monster->y);
// Are we in something..
if(ccell == -1){
// Can we move above
if(px_SceneGet(scene, monster->x, monster->y - 1) == 0){
monster->y -= 1;
}
else{
// Kill
px_SoundPlay("res/sounds/entities/kill.wav", 2);
monster->active = false;
}
}
// Are we in a standstill..
if(standstill > 4){
// Kill
px_SoundPlay("res/sounds/entities/kill.wav", 2);
monster->active = false;
}
}
void px_MGCHECK(PX_Monster* monster, PX_Scene* scene){
// Are we on the floor?
if(monster->y + 2 > GRIDY){
monster->grounded = true;
return;
}
// What's the tile below us?
int below = px_SceneGet(scene, monster->x, monster->y + 1);
// Is it ground?
monster->grounded = below != 0;
}
void px_MCORRUPT(PX_Monster* monster, PX_Scene* scene){
// Grounded?
if(!monster->grounded) {return;}
// Corrupt when it's time
if(ftime > FALLT){
ftime = 0;
if(monster->y + 2 < GRIDY){
px_ScenePlot(scene, monster->x, monster->y + 1, 0);
// Playing a sound
px_SoundPlay("res/sounds/entities/corrupt.wav", 2);
// Should we stand still?
int shouldStand = rand() % 50;
if(shouldStand > 10){
standstill = 0;
}
}
}
else{
ftime += deltatime * FALLSLICE;
}
}
// --HEADER
PX_Monster px_MonsterCreate(SDL_Renderer* renderer){
// Holding
PX_Monster monster;
// Setting variables
monster.grounded = false;
monster.active = false;
monster.x = 3;
monster.y = 0;
// Creating the texture
monster_tex = px_TextureCreate(renderer, "res/sprites/monster.png");
// Returning monster
return monster;
}
void px_MonsterUpdate(PX_Monster* monster, PX_Scene* scene){
// Active?
if(!monster->active) {px_MACTIVATE(monster); return;}
// Checks
px_MGCHECK(monster, scene);
// Physics
px_MSTRIDE(monster, scene);
px_MFALL(monster, scene);
// Effects
px_MCORRUPT(monster, scene);
// Checks
px_MKILL(monster, scene);
}
void px_MosnterDraw(SDL_Renderer* renderer, PX_Scene* scene, PX_Monster* monster){
// Active?
if(!monster->active) {return;}
// Making shapes
SDL_Rect rect;
// Constants
const int _xgrid = scene->width / GRIDX;
const int _ygrid = scene->height / GRIDY;
// Updating positional values
rect.x = monster->x * _xgrid; rect.y = monster->y * _ygrid;
rect.w = _xgrid; rect.h = _ygrid;
// Set Color
SDL_SetRenderDrawColor(renderer, 255,255,255, 1);
SDL_RenderFillRect(renderer, &rect);
// Drawing texture
SDL_RenderCopy(renderer, monster_tex, NULL, &rect);
}

32
src/gme/monster.h Normal file
View file

@ -0,0 +1,32 @@
// Define once
#ifndef H_MONSTER
#define H_MONSTER
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// --HEADERS
#include "../gme/scene.h"
#include "../app/texture.h"
#include "../app/dtime.h"
// Structures
typedef struct PX_Monster{
int x; int y;
bool grounded;
bool active;
} PX_Monster;
// Variables
SDL_Texture* monster_tex;
// Functions
PX_Monster px_MonsterCreate(SDL_Renderer* renderer);
void px_MonsterUpdate(PX_Monster* monster, PX_Scene* scene);
void px_MosnterDraw(SDL_Renderer* renderer, PX_Scene* scene, PX_Monster* monster);
// End definition
#endif

191
src/gme/scene.c Normal file
View file

@ -0,0 +1,191 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// --HEADERS
#include "scene.h"
#include "../app/texture.h"
#include "../app/sound.h"
#include "../app/dtime.h"
// Functions
// Variables
int redRows = 0;
float redTime = 0;
// --HEADER
PX_Scene px_SceneCreate(SDL_Renderer* renderer, int width, int height){
// Making the structure
PX_Scene scene = {
{
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
},
width, height,
0
};
// Setting something Important
gameOver = false;
redRows = 0;
redTime = 0;
// Loading textures
celltex = px_TextureCreate(renderer, "res/sprites/cell.png");
SDL_SetTextureBlendMode(celltex, SDL_BLENDMODE_BLEND);
return scene;
}
void px_SceneDelete(PX_Scene* scene){
free(scene);
}
void px_ScenePlot(PX_Scene* scene, int x, int y, int value){
// Plotting based on thing
scene->matricies[y*GRIDX+x] = value;
}
int px_SceneGet(PX_Scene* scene, int x, int y){
return scene->matricies[y*GRIDX+x];
}
void px_SceneDraw(PX_Scene* scene, SDL_Renderer* renderer){
// Drawing our scene every x&y coords
for(int y = 0; y < GRIDY; y++){
// For the awesomeness!
int cellsfilled = 0;
for(int x = 0; x < GRIDX; x++){
// Helpers
bool filled;
// Color
SDL_SetRenderDrawColor(renderer, 134,134,134, 1);
// Game over?
if(gameOver){
if(y <= redRows){
filled = true;
SDL_SetRenderDrawColor(renderer, 255, 55, 55, 1);
SDL_SetTextureColorMod(celltex, 255, 55, 55);
}
else{
SDL_SetRenderDrawColor(renderer, 134,134,134, 1);
SDL_SetTextureColorMod(celltex, 134, 134, 134);
}
if(redTime >= 240.0f){
redTime = 0;
redRows += 1;
}
else{
redTime += deltatime * (120.0f/1000.0f);
}
}
else{
// Setting color
// What type of cell is it?
if(scene->matricies[y*GRIDX+x] == -1){
SDL_SetTextureColorMod(celltex, 175,200,175);
cellsfilled += 1;
filled = true;
}
else if(scene->matricies[y*GRIDX+x] != 0){
SDL_SetTextureColorMod(celltex, 225,225,255);
filled = true;
}
else{
SDL_SetTextureColorMod(celltex, 100,100,100);
filled = false;
}
}
// Getting the size difference from window
const int _xgrid = scene->width / GRIDX;
const int _ygrid = scene->height / GRIDY;
// Making the rectangle
SDL_Rect rect;
// Placing rect
rect.x = x * _xgrid;
rect.y = y * _ygrid;
rect.w = _xgrid; rect.h = _ygrid;
// Drawing rect
if(filled){
SDL_RenderFillRect(renderer, &rect);
SDL_RenderCopy(renderer, celltex, NULL, &rect);
}
else{
SDL_RenderDrawRect(renderer, &rect);
}
// Clear board!
// -- USELESS CODE!
// Making it so that it'll be able
// to hold all prior cells
// scene->matricies[y*GRIDX+x] = 0;
}
// Were all the cells filled?
if(cellsfilled >= GRIDX){
// Playing the sound
px_SoundPlay("res/sounds/clear.wav", 0);
// Clearing rows
for(int cy = y; cy > 0; cy--){
for(int x = 0; x < GRIDX; x++){
scene->matricies[cy*GRIDX+x] = scene->matricies[(cy-1)*GRIDX+x];
}
}
// The effect
for(int ts = 0; ts < 3; ts++){
for(int x = 0; x < GRIDX; x++){
// Effect Color
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 1);
// Getting the size difference from window
const int _xgrid = scene->width / GRIDX;
const int _ygrid = scene->height / GRIDY;
// Making the rectangle
SDL_Rect rect;
// Placing rect
rect.x = x * _xgrid;
rect.y = y * _ygrid;
rect.w = _xgrid; rect.h = _ygrid;
SDL_RenderFillRect(renderer, &rect);
// Drawing cool things
SDL_RenderPresent(renderer);
SDL_Delay(20);
}
}
// Points?
scene->score += 100;
printf("New Score: %i\n", scene->score);
}
}
}

44
src/gme/scene.h Normal file
View file

@ -0,0 +1,44 @@
// Define once
#ifndef H_SCENE
#define H_SCENE
// Files
// --SYSTEM
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
// --HEADERS
#include "tetriminos.h"
#include "../app/sound.h"
/*
For this, The scene will be a
9x16 grid = 144
*/
// CONSTANTS
#define GRIDX 9
#define GRIDY 16
// Structure
typedef struct PX_Scene{
int matricies[144];
int width, height;
int score;
} PX_Scene;
// Variables
SDL_Texture* celltex;
bool gameOver;
// Functions
PX_Scene px_SceneCreate(SDL_Renderer* renderer, int width, int height);
void px_SceneDelete(PX_Scene* scene);
void px_ScenePlot(PX_Scene* scene, int x, int y, int value);
int px_SceneGet(PX_Scene* scene, int x, int y);
void px_SceneDraw(PX_Scene* scene, SDL_Renderer* renderer);
// End definition
#endif

423
src/gme/tetrimino.c Normal file
View file

@ -0,0 +1,423 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
// --HEADERS
#include "tetrimino.h"
#include "../app/sound.h"
#include "../app/dtime.h"
// CONSTANTS
#define FTIME 120.0f/1000.0f
// Functions
// --HELPERS
/*
Helper Function Format:
void px_T[FUNCTION NAME](PX_Tetrimino* tetrimino);
Also no, I'm not going to use TYPEDEF for my structures.
I do NOT know how to use those haha
*/
// ----DRAWING
// ----COLLISION
bool px_TCOLLIDING(PX_Tetrimino* tetrimino, PX_Scene* scene){
for(int y = 0; y < 4; y++){
// Lets be sure we're not on the ground.
if(tetrimino->y + y + 1 > GRIDY || tetrimino->y + y - 1 < 0){
break;
}
// All X's
for(int x = 0; x < 4; x++){
// Current tile:
int ctile = px_SceneGet(scene, tetrimino->x + x, tetrimino->y + y);
// Is this tile VALID
if(ctile == tetrimino->type + 1){
// Get the thing below us:
int belowTile = px_SceneGet(scene, tetrimino->x + x, tetrimino->y + y + 1);
// Is something below us?
if(belowTile != 0 && belowTile != tetrimino->type + 1){
return true;
}
}
}
}
// Not a success
return false;
}
bool px_TOVEREDGE(PX_Tetrimino* tetrimino, PX_Scene* scene, int xoffset, int yoffset){
int width, start;
width = 0; start = 4;
// What is our width?
for(int y = 0; y < 4; y++){
for(int x = 0; x < 4; x++){
// What's our cell?
int ccell = px_SceneGet(scene, tetrimino->x + x, tetrimino->y + y);
// Is our cell valid
if(ccell == tetrimino->type + 1){
// Setting stuff
if(x < start) { start = x; }
if(width < x) { width = x; }
}
}
}
// Giving the piece its info
tetrimino->width = width;
// Can we move?
return tetrimino->x + start + xoffset < 0
|| tetrimino->x + width + (xoffset + 1) > GRIDX;
}
// ----PHYSICS
void px_TFALL(PX_Tetrimino* tetrimino){
if(tetrimino->ft > 4){
tetrimino->y += 1;
tetrimino->ft = 0;
}
else{
tetrimino->ft += FTIME * deltatime;
}
}
void px_TBORDER(PX_Tetrimino* tetrimino, PX_Scene* scene){
if(tetrimino->y >= GRIDY - 2){
// Playing the sound
if(!tetrimino->dropping){
px_SoundPlay("res/sounds/tetrimino/drop.wav", 1);
}
tetrimino->still = true;
}
}
void px_TDRAW(PX_Tetrimino* tetrimino, PX_Scene* scene, int x, int y, int spriteval){
// Placeholding someting?
const int tetdrawtype = tetrimino->type + 1;
int width = 0;
// What is our width?
switch(tetrimino->type){
case 0:
width = 4; break;
case 1:
case 2:
case 4:
case 5:
case 6:
case 7:
width = 3; break;
case 3:
width = 2; break;
}
// This is the value of the cell we're trying to get
int cellv = px_SceneGet(scene, x+tetrimino->x, y+tetrimino->y);
if( cellv == 0
|| cellv == tetdrawtype){
// Are we still?
if(tetrimino->still){
px_ScenePlot(scene, x + tetrimino->x, y + tetrimino->y, spriteval * -1);
}
else{
px_ScenePlot(scene, x + tetrimino->x, y + tetrimino->y, spriteval * tetdrawtype);
}
}
// Are the cells above avalible?
if((tetrimino->y - 1) * GRIDY + tetrimino->x > 0){
// Clearing cells above
for(int c = 0; c < width; c++){
px_ScenePlot(scene, c + tetrimino->x, tetrimino->y - 1, 0);
}
}
}
void px_TCHECKOTHER(PX_Tetrimino* tetrimino, PX_Scene* scene){
// This is so that we're able to detect if we're colliding with another block
// Only the top part will be detected now
/*
-- NEW SYSTEM OF COLLISION!
This system will account for
rotations
*/
if(px_TCOLLIDING(tetrimino, scene)){
tetrimino->still = true;
// The sound
if(!tetrimino->dropping){
px_SoundPlay("res/sounds/tetrimino/drop.wav", 1);
}
// Are we gamed over?
if(tetrimino->y <= 2){
tet_gameOver = true;
}
}
}
// --REGULARS
PX_Tetrimino px_TetriminoCreate(){
// Making stuff
PX_Tetrimino tetrimino;
// Assigning Variables
tetrimino.x = 3;
tetrimino.y = 1;
tetrimino.width = 0;
tetrimino.ft = 0;
tetrimino.type = 1;
tetrimino.still = false;
tetrimino.dropping = false;
tet_gameOver = false;
// Giving back tetrimino
return tetrimino;
}
void px_TetriminoDelete(PX_Tetrimino* tetrimino){
free(tetrimino);
}
void px_TetriminoReset(PX_Tetrimino* tetrimino){
tetrimino->still = false;
tetrimino->dropping = false;
tetrimino->y = 0;
tetrimino->x = 3;
tetrimino->ft = 0;
tetrimino->type += 1;
tetrimino->rotation = 0;
if(tetrimino->type >= 7) {tetrimino->type = 1;}
}
void px_TetriminoUpdate(PX_Tetrimino* tetrimino, PX_Scene* scene){
// Are we static?
if(tetrimino->still) {printf("STILL\n"); return;}
// Physics
px_TFALL(tetrimino);
px_TCHECKOTHER(tetrimino, scene);
// Checks
px_TBORDER(tetrimino, scene);
}
void px_TetriminoDraw(PX_Tetrimino* tetrimino, PX_Scene* scene){
/*
Rotations, are complicated.
Let's use a little cheat to get through it!
*/
// Going through X and Y
for (int wy = 0; wy < 4; wy ++){
for (int wx = 0; wx < 4; wx ++){
// Sorting out the rotation stuff
int x,y;
// Flipping?
switch(tetrimino->rotation){
case 0: // Up
x = wx;
y = wy;
break;
case 1: // Right
x = wy;
y = 2 - wx;
break;
case 2: // Down
x = 2 - wx;
y = 2 - wy;
break;
case 3: // Left
x = 2 - wy;
y = wx;
break;
}
// Going through each type
switch(tetrimino->type){
// The I piece
case 0:
px_TDRAW(tetrimino, scene, wx,wy, te_I[y*4+x]);
break;
// The J piece
case 1:
px_TDRAW(tetrimino, scene, wx,wy, te_J[y*4+x]);
break;
// The L piece
case 2:
px_TDRAW(tetrimino, scene, wx,wy, te_L[y*4+x]);
break;
// The O piece
case 3:
px_TDRAW(tetrimino, scene, wx,wy, te_O[y*4+x]);
break;
// The S piece
case 4:
px_TDRAW(tetrimino, scene, wx,wy, te_S[y*4+x]);
break;
// The T piece
case 5:
px_TDRAW(tetrimino, scene, wx,wy, te_T[y*4+x]);
break;
// The Z piece
case 6:
px_TDRAW(tetrimino, scene, wx,wy, te_Z[y*4+x]);
break;
default:
break;
}
}
}
}
void px_TetriminoMove(PX_Tetrimino* tetrimino, PX_Scene* scene, int x, int y){
// Moving the wanted tetrimino
// Appropriate?
if(px_TOVEREDGE(tetrimino, scene, x, 0)) {return;}
// Moving
tetrimino->x += x;
// Playing a sound
px_SoundPlay("res/sounds/tetrimino/move.wav", 1);
// Clearing cells on the side it was moving away from
// If this doesn't happen, GLITCHES happen..
if(x > 0){ // Moving Right
for(int y = 0; y < 4; y++){
// Getting the point
int cellv = px_SceneGet(scene, tetrimino->x - 1, tetrimino->y + y - 1);
if(cellv == tetrimino->type + 1){
px_ScenePlot(scene, tetrimino->x - 1, tetrimino->y + y - 1, 0);
}
}
}
else if(x < 0){ // Moving Left
// Are we going to cause a index out of range crash?
if((tetrimino->y - 1) * GRIDY + tetrimino->x > 0){
for(int y = 0; y < 4; y++){
// Getting the point
int cellv = px_SceneGet(scene, tetrimino->x + tetrimino->width + 1, tetrimino->y + y);
if(cellv == tetrimino->type + 1){
px_ScenePlot(scene, tetrimino->x + tetrimino->width + 1, tetrimino->y + y, 0);
}
}
}
}
}
void px_TetriminoDrop(PX_Tetrimino* tetrimino, PX_Scene* scene){
// Dropping the tetrimino
// These are our helpers
bool didDrop = false;
int height, width, xoff;
// Whats our height?
height = tetrimino->y + 1;
// Whats our width?
switch(tetrimino->type){
case 1:
case 2:
case 5:
width = 3; xoff = 0; break;
case 4:
case 3:
width = 2; xoff = 0; break;
case 6:
width = 2; xoff = 1; break;
}
// Avalible points?
if(tetrimino->y * GRIDY + tetrimino->x > 0){
// Resetting surrounding graphics
for(int y = 0; y < 4; y++){
for(int x = 0; x < 4; x++){
if(px_SceneGet(scene, tetrimino->x + x, tetrimino->y + y - 1) == tetrimino->type + 1){
px_ScenePlot(scene, tetrimino->x + x, tetrimino->y + y - 1, 0);
}
}
}
}
// Dropping!
while(!didDrop && !tetrimino->still){
// Going through the width
for(int x = 0; x < width; x++){
// Are we on the ground?
if(height + 2 > GRIDY){
didDrop = true;
break;
}
else{
// Checking others
if(px_TCOLLIDING(tetrimino, scene)){
didDrop = true;
break;
}
}
}
// Did we escape?
if(didDrop){
// Playing the sound
px_SoundPlay("res/sounds/tetrimino/slam.wav", 1);
break;
}
// KEEP FALLING!
else{
// Falling
tetrimino->y += 1;
height = tetrimino->y + 1;
// Drawing so it's consistent
px_TetriminoDraw(tetrimino, scene);
}
}
// We're still
// So play the cool sound!
tetrimino->dropping = true;
// Drop imidiatly.
tetrimino->ft = 4;
// Just to buffer
SDL_Delay(25);
}
void px_TetriminoRotate(PX_Tetrimino* tetrimino, PX_Scene* scene, int direction){
// Dumb types
if(tetrimino->type == 3) {return;}
// Are we avalible to turn?
if(px_TOVEREDGE(tetrimino, scene, direction, 0)) {return;}
// Rotating
tetrimino->rotation += direction;
// Clamping
if(tetrimino->rotation < 0){
tetrimino->rotation = 3;
}
if(tetrimino->rotation > 3){
tetrimino->rotation = 0;
}
// New rotation?
printf("Rotation: %i\n", tetrimino->rotation);
}

45
src/gme/tetrimino.h Normal file
View file

@ -0,0 +1,45 @@
// Define once
#ifndef H_TETRIMINO
#define H_TETRIMINO
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
// --HEADERS
#include "scene.h"
#include "../app/sound.h"
// Structures
typedef struct PX_Tetrimino{
// Variables
int x,y;
int width;
int type;
int rotation;
// Cases
bool still, dropping;
// Timers
float ft;
} PX_Tetrimino;
// Variables
bool tet_gameOver;
// Functions
PX_Tetrimino px_TetriminoCreate();
void px_TetriminoDelete(PX_Tetrimino* tetrimino);
void px_TetriminoUpdate(PX_Tetrimino* tetrimino, PX_Scene* scene);
void px_TetriminoDraw(PX_Tetrimino* tetrimino, PX_Scene* scene);
void px_TetriminoReset(PX_Tetrimino* tetrimino);
void px_TetriminoMove(PX_Tetrimino* tetrimino, PX_Scene* scene, int x, int y);
void px_TetriminoDrop(PX_Tetrimino* tetrimino, PX_Scene* scene);
void px_TetriminoRotate(PX_Tetrimino* tetrimino, PX_Scene* scene, int direction);
// End definition
#endif

62
src/gme/tetriminos.c Normal file
View file

@ -0,0 +1,62 @@
// File
#include "tetriminos.h"
/*
-- This is a zero'd out thing --
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0
*/
// Pieces
int te_I[16] = {
0,0,0,0,
1,1,1,1,
0,0,0,0,
0,0,0,0
};
// -- THE J PIECE
int te_J[16] = {
1,0,0,0,
1,1,1,0,
0,0,0,0,
0,0,0,0
};
int te_L[16] = {
0,0,1,0,
1,1,1,0,
0,0,0,0,
0,0,0,0
};
int te_O[16] = {
1,1,0,0,
1,1,0,0,
0,0,0,0,
0,0,0,0
};
int te_S[16] = {
0,1,1,0,
1,1,0,0,
0,0,0,0,
0,0,0,0
};
int te_T[16] = {
0,1,0,0,
1,1,1,0,
0,0,0,0,
0,0,0,0
};
int te_Z[16] = {
1,1,0,0,
0,1,1,0,
0,0,0,0,
0,0,0,0
};

30
src/gme/tetriminos.h Normal file
View file

@ -0,0 +1,30 @@
// Define once
#ifndef H_TETRIMINOS
#define H_TETRIMINOS
/*
This file will hold all the tetrminos
the player will have at store to use!
Each shape will be "Referenced"
as a 4x4 grid. So 16 cells.
In the "Scene", it will be a BOOLEAN
MATRIX. So 1 represents something,
and 0 represents nothing!
All of these will begin with:
const int te_
*/
int te_I[16];
int te_J[16];
int te_L[16];
int te_O[16];
int te_S[16];
int te_T[16];
int te_Z[16];
// End definition
#endif

127
src/main.c Normal file
View file

@ -0,0 +1,127 @@
/*
-- BLOKOS --
A simple Tetris Re-Make for my Computer Science
class In May of 2022. I'm going to choose the
C language, because it makes the Most sense to me.
My code may be a little sloppy, so if there's anything horrible,
feel free to let me know!
*/
// For SDL(WINDOWS)
#define SDL_MAIN_HANDLED
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --HEADERS
#include "app/window.h"
#include "app/renderer.h"
#include "gme/scene.h"
#include "gme/tetrimino.h"
// --BASE
#include "app/dtime.h"
#include "app/prefs.h"
#include "app/saves.h"
// --SCREENS
#include "scn/gameplay.h"
#include "scn/mainmenu.h"
#include "scn/splash.h"
// Variables
int cscrn;
bool rtt;
// Functions
void switchscrn(){
// Getting key state
const Uint8* ks = SDL_GetKeyboardState(NULL);
// If Space is pressed
if(ks[SDL_SCANCODE_SPACE] && px_mcanstart){
rtt = true;
}
else if(!(ks[SDL_SCANCODE_SPACE]) && rtt){
if(cscrn == 0) { blk_MMClean(); }
cscrn += 1;
rtt = false;
}
}
// Entry Point
int main(int argc, char* argv[]){
// This is our starting point
// Prefrences
PX_PrefrenceResult prefs = px_ReadPrefs();
// Loading save game
PX_SaveGame saveGame = px_saveRead("res/saves/save.conf");
// Creating a window
PX_Window window = px_WindowCreate("BLOKOS", prefs.width, prefs.height);
SDL_Renderer* renderer = px_RendererCreate(window.window);
// Screen state
cscrn = -1; rtt = false;
// Starting the Sound System
px_SoundStart();
// Making the game screen
px_SSstart(renderer, window.width, window.height);
blk_MMCreate(renderer);
blk_GameStart(renderer, &saveGame);
// Game Loop
while(window.opened){
// Update window
px_WindowUpdate(&window);
// Clear screen
px_RendererClear(renderer);
// Getting Delta Time
updateTime();
// Switching between screens
switch(cscrn){
case -1:
// Game code..
px_SSupdate();
if(px_ssready) {cscrn = 0; px_SSclean();}
// Render code..
px_SSdraw(renderer, window.width, window.height);
break;
case 0:
// Game code..
blk_MMUpdate();
switchscrn();
// Render code..
blk_MMDraw(renderer);
// End screen
break;
case 1:
// Game code..
blk_GameUpdate(&saveGame);
// Render code..
blk_GameDraw(renderer);
// End screen
break;
}
// Display screen
px_RendererDisplay(renderer);
}
// Cleanup
px_TetriminoDelete(&tetrimino);
px_SceneDelete(&scene);
px_RendererDelete(renderer);
px_WindowDelete(&window);
// Exiting the app
return 0;
}

170
src/scn/gameplay.c Normal file
View file

@ -0,0 +1,170 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "gameplay.h"
#include "../app/saves.h"
#include "../gme/monster.h"
// Variables
PX_Monster monster;
bool didWrite = false;
// Functions
// --HELPER
void game_MoveTetrimino(){
const Uint8* ks = SDL_GetKeyboardState(NULL);
if(!didpress){
if(ks[SDL_SCANCODE_LEFT]){
// TODO: IMPLEMENT
px_TetriminoMove(&tetrimino, &scene, -1, 0);
}
else if(ks[SDL_SCANCODE_RIGHT]){
// TODO: IMPLEMENT
px_TetriminoMove(&tetrimino, &scene, +1, 0);
}
else if(ks[SDL_SCANCODE_DOWN]){
px_TetriminoMove(&tetrimino, &scene, 0, +2);
}
else if(ks[SDL_SCANCODE_SPACE]){
px_TetriminoDrop(&tetrimino, &scene);
}
else if(ks[SDL_SCANCODE_Z]){
px_TetriminoRotate(&tetrimino, &scene, -1);
}
else if(ks[SDL_SCANCODE_X]){
px_TetriminoRotate(&tetrimino, &scene, 1);
}
else{
// No keys, Do nothing!
return;
}
// We did press a key
didpress = true;
}
else if((!ks[SDL_SCANCODE_LEFT])
&& (!ks[SDL_SCANCODE_RIGHT])
&& (!ks[SDL_SCANCODE_DOWN])
&& (!ks[SDL_SCANCODE_SPACE])
&& (!ks[SDL_SCANCODE_Z])
&& (!ks[SDL_SCANCODE_X])){
didpress = false;
}
}
void game_UpdateScore(SDL_Renderer* renderer){
// A color?
SDL_Color fg = {
255,255,255, 255
};
// New Score
char* nst[10];
sprintf(nst, "%d", scene.score);
// Making surface
if(! (score_num_txt.surface = TTF_RenderText_Solid(score_num_txt.font, nst, fg))){
printf("Failed to update Score(number) Surface\n");
return;
}
// Updating the texture
if(! (score_num_txt.texture = SDL_CreateTextureFromSurface(renderer, score_num_txt.surface))){
printf("Failed to update Score(number) Texture\n");
return;
}
score_num_txt.width = score_num_txt.surface->w;
// Cleanup
SDL_FreeSurface(score_num_txt.surface);
}
// --HEADER
void blk_GameStart(SDL_Renderer* renderer, PX_SaveGame* savegame){
// Making a scene
scene = px_SceneCreate(renderer, 300, 512);
tetrimino = px_TetriminoCreate();
// Making other elements
score_txt = px_TextCreate(renderer, "SCORE: ");
score_num_txt = px_TextCreate(renderer, "0");
highscore_txt = px_TextCreate(renderer, "HIGH SCORE: ");
// Our high score!
char high_score[16];
sprintf(high_score, "%d", savegame->high_score);
highscore_num_txt = px_TextCreate(renderer, high_score);
// Making entities
monster = px_MonsterCreate(renderer);
}
void blk_GameUpdate(PX_SaveGame* savegame){
// Game over..
if(gameOver){
// Doing an effect
// Saving the score
if(scene.score > savegame->high_score && !didWrite){
printf("Rewrighting high score from %i to %i!\n", savegame->high_score, scene.score);
char scoreval[16];
sprintf(scoreval, "%d", scene.score);
printf("Score value: %s\n", scoreval);
px_saveWrite("save.conf", "high_score", scoreval);
didWrite = true;
}
return;
}
px_TetriminoUpdate(&tetrimino, &scene);
if(tetrimino.still){
/*
-- THIS CODE WOULD DO THIS --
It would "delete" the current block,
and place it to the top of the screen.
*/
// This part of the code will spawn in a NEW block and keep the old one!
px_TetriminoDraw(&tetrimino, &scene);
px_TetriminoReset(&tetrimino);
}
// Moving the tetrimino
game_MoveTetrimino();
// Are we gamed over
if(tet_gameOver){
gameOver = true;
px_SoundPlay("res/sounds/die.wav", 0);
}
// Updating Entities
px_MonsterUpdate(&monster, &scene);
}
void blk_GameDraw(SDL_Renderer* renderer){
// World drawing and Scene drawing
px_TetriminoDraw(&tetrimino, &scene);
px_SceneDraw(&scene, renderer);
// Text Updates
game_UpdateScore(renderer);
px_TextDraw(renderer, score_txt, 300, 150, 112, 40);
px_TextDraw(renderer, score_num_txt, 400, 150, (int)(score_num_txt.width * 1.5f), 40);
px_TextDraw(renderer, highscore_txt, 300, 200, 112, 40);
px_TextDraw(renderer, highscore_num_txt, 400, 200, (int)(highscore_num_txt.width * 1.5f), 40);
// Drawing entities
px_MosnterDraw(renderer, &scene, &monster);
}

32
src/scn/gameplay.h Normal file
View file

@ -0,0 +1,32 @@
// Define once
#ifndef H_GAMEPLAY
#define H_GAMEPLAY
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "../gme/scene.h"
#include "../gme/tetrimino.h"
#include "../app/text.h"
#include "../app/saves.h"
#include "../gme/monster.h"
// Scene Variables
PX_Tetrimino tetrimino;
PX_Scene scene;
bool didpress;
// Texts
PX_Text score_txt, highscore_txt;
PX_Text score_num_txt, highscore_num_txt;
// Functions
void blk_GameStart(SDL_Renderer* renderer, PX_SaveGame* savegame);
void blk_GameUpdate(PX_SaveGame* savegame);
void blk_GameDraw(SDL_Renderer* renderer);
// End definition
#endif

73
src/scn/mainmenu.c Normal file
View file

@ -0,0 +1,73 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "../app/features.h"
#include "../app/texture.h"
#include "../app/dtime.h"
#include "../app/text.h"
#include "mainmenu.h"
// Variables
float _time;
float stpos;
// Functions
// --HELPER
void blk_MMSTART(){
stpos = Lerp(stpos, 350, 0.05f);
if(stpos <= 353){
stpos = 350;
px_mcanstart = true;
}
}
// --BASE
void blk_MMCreate(SDL_Renderer* renderer){
// Init SDL2_IMG
IMG_Init(IMG_INIT_PNG);
// Creating textures and what not
titletex = (SDL_Texture*)malloc(16 * sizeof(int));
titletex = px_TextureCreate(renderer, "res/sprites/title.png");
// Making the title thing
start_txt = px_TextCreate(renderer, "Press [SPACE] to start.");
// Making the time
_time = 0;
stpos = 600;
px_mcanstart = false;
}
void blk_MMUpdate(){
// Adding time
_time += (float)deltatime * 1.2f;
// Allowing the menu to transition
blk_MMSTART();
}
void blk_MMDraw(SDL_Renderer* renderer){
// Color
SDL_SetRenderDrawColor(renderer, 0,0,0, 1);
// Making the title card
SDL_Rect titlecard;
titlecard.x = 100 + (int)(cosf(_time / 200) * 10);
titlecard.y = 10 + (int)(sinf(_time / 100) * 10);
titlecard.w = 300; titlecard.h = 300;
SDL_RenderFillRect(renderer, &titlecard);
SDL_RenderCopy(renderer, titletex, NULL, &titlecard);
// Making the start text
px_TextDraw(renderer, start_txt, 100, stpos, 300, 50);
}
void blk_MMClean(){
SDL_FreeSurface(start_txt.surface);
free(titletex);
}

27
src/scn/mainmenu.h Normal file
View file

@ -0,0 +1,27 @@
// Define once
#ifndef H_MAINMENU
#define H_MAINMENU
// Files
// --SYSTEM
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// --HEADERS
#include "../app/text.h"
// CONSTANTS
// VARIABLES
SDL_Texture* titletex;
PX_Text start_txt;
bool px_mcanstart;
// Functions
void blk_MMCreate(SDL_Renderer* renderer);
void blk_MMUpdate();
void blk_MMDraw(SDL_Renderer* renderer);
void blk_MMClean();
// End definition
#endif

91
src/scn/splash.c Normal file
View file

@ -0,0 +1,91 @@
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "splash.h"
#include "../app/features.h"
#include "../app/texture.h"
#include "../app/dtime.h"
#include "../app/sound.h"
// Variables
SDL_Texture* splashtex;
int wid, hig;
int spx,spy;
int spf;
float stillt;
bool fading, playedding;
// Functions
void px_SSstart(SDL_Renderer* renderer, int width, int height){
// Making a texture
splashtex = (SDL_Texture*)malloc(32 * sizeof(int));
splashtex = px_TextureCreate(renderer, "res/sprites/primax.png");
SDL_SetTextureBlendMode(splashtex, SDL_BLENDMODE_BLEND);
// Setting variables
px_ssready = false;
playedding = false;
fading = false;
wid = width; hig = height;
spx = (int)(width / 2);
spy = (int)(height * 1.5f);
spf = 255;
}
void px_SSupdate(){
// Moving the logo to center
spy = Lerp(spy, hig / 2, 0.05f);
// Are we ready?
if(abs(spy - (hig / 2)) <= 5){
if(stillt >= 5.0f){
fading = true;
}
else{
stillt += deltatime * (120.0f/1000.0f);
}
if(!playedding){
px_SoundPlay("res/sounds/primaxding.wav", 0);
playedding = true;
}
}
if(fading){ // Fading
spf = Lerp(spf, 0, 0.02f * deltatime);
if(spf <= 3) {px_ssready = true;}
}
}
void px_SSdraw(SDL_Renderer* renderer, int width, int height){
// The clear color
SDL_SetRenderDrawColor(renderer, 0,0,0, 1);
// Making the rect
SDL_Rect rect;
// Constants
const int rsize = 400;
// Setting the positional stuff
rect.w = rsize; rect.h = rsize;
rect.x = spx - (int)(rsize / 2.0f);
rect.y = spy - (int)(rsize / 2.0f);
SDL_SetTextureAlphaMod(splashtex, spf);
// Drawing the rectangle
SDL_RenderFillRect(renderer, &rect);
SDL_RenderCopy(renderer, splashtex, NULL, &rect);
}
void px_SSclean(){
// Free All variables
free(splashtex);
}

24
src/scn/splash.h Normal file
View file

@ -0,0 +1,24 @@
// Define once
#ifndef H_SPLASH
#define H_SPLASH
// Files
// --SYSTEM
#include <stdio.h>
#include <stdbool.h>
// --SDL
#include <SDL2/SDL.h>
// --HEADERS
#include "../app/dtime.h"
// Variables
bool px_ssready;
// Functions
void px_SSstart(SDL_Renderer* renderer, int width, int height);
void px_SSupdate();
void px_SSdraw(SDL_Renderer* renderer, int width, int height);
void px_SSclean();
// End definition
#endif