olc::CodeJam 2022 Entry #olcCodeJam2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Seasons-Of-Loneliness/SeasonsOfLoneliness.cpp

315 lines
7.6 KiB

#define OLC_PGE_APPLICATION
#include "pixelGameEngine.h"
#include "data.h"
using namespace std;
enum GAMESTATE{
CUTSCENE_1,
CUTSCENE_2,
GAMEWORLD
};
enum TILES{
DIRT,
GRASS,
WATER
};
enum CUTSCENE{
PAN_DOME,
};
#define WIDTH 256
#define HEIGHT 224
#define ALPHA_SCREEN1 128
#define ALPHA_SCREEN2 20
#define FADE_SPD 6
#define MOVE_SPD 0.01
class Object{
public:
float x,y;
olc::Decal*spr;
};
class SeasonsOfLoneliness : public olc::PixelGameEngine
{
public:
SeasonsOfLoneliness()
{
sAppName = "Seasons of Loneliness";
}
public:
GAMESTATE GAME_STATE=CUTSCENE_1;
int textInd=0;
int cursorX=0;
int transitionTime=0;
bool fade=false;
int transparency=0;
int frameCount=0;
float elapsedTime=0;
const float TARGET_RATE = 1/60.0;
std::string CUTSCENE_CONSOLE_TEXT = "";
int**MAP=NULL;
int MAP_WIDTH=-1;
int MAP_HEIGHT=-1;
olc::Decal*TILES;
float PLAYER_COORDS[2] = {};
std::vector<Object> OBJECTS;
bool CUTSCENE_ACTIVE=false;
CUTSCENE CURRENT_CUTSCENE=PAN_DOME;
int CUTSCENE_TIMER=0;
bool CUTSCENE_FLAGS[8];
olc::Decal*DOME_DECAL;
std::map<std::string,olc::Decal*> BASE_OBJECTS;
void LoadMap(char*mapName) {
std::ifstream f("assets/maps/map1");
std::string data;
MAP_WIDTH=MAP_HEIGHT=-1;
if (MAP!=NULL) {
for (int y=0;y<MAP_HEIGHT;y++) {
free(MAP[y]);
}
free(MAP);
}
int y=0;
if (f.is_open()) {
while (f.good()) {
f>>data;
if (MAP_WIDTH==-1) {
std::stringstream stream(data);
stream>>MAP_WIDTH;
} else
if (MAP_HEIGHT==-1) {
std::stringstream stream(data);
stream>>MAP_HEIGHT;
} else
if (y<MAP_HEIGHT) {
if (MAP==NULL) {
MAP=(int**)malloc(sizeof(int**)*MAP_HEIGHT);
}
MAP[y]=(int*)malloc(sizeof(int*)*MAP_WIDTH);
for (int i=0;i<data.length();i++) {
MAP[y][i]=data[i]-'0';
}
y++;
} else {
Object obj;
std::stringstream split1(data.substr(0,data.find(';')));
split1>>obj.x;
std::stringstream split2(data.substr(data.find(';')+1,data.find(';',data.find(";")+1)-(data.find(';')+1)));
split2>>obj.y;
std::string split3 = data.substr(data.find(';',data.find(";")+1)+1,data.length()-(data.find(';',data.find(";")+1)+1));
obj.spr=BASE_OBJECTS[split3];
printf("Loaded object %s: (%f,%f)\n",split3.c_str(),obj.x,obj.y);
OBJECTS.push_back(obj);
}
}
}
printf("Loaded %dx%d map:\n",MAP_WIDTH,MAP_HEIGHT);
for (int y=0;y<MAP_HEIGHT;y++) {
for (int x=0;x<MAP_WIDTH;x++) {
printf("%d",MAP[y][x]);
}
printf("\n");
}
}
bool OnUserCreate() override
{
SetPixelMode(olc::Pixel::ALPHA);
//ConsoleCaptureStdOut(true);
// Called once at the start, so create things here
TILES=new olc::Decal(new olc::Sprite("assets/tiles.png"));
DOME_DECAL=new olc::Decal(new olc::Sprite("assets/dome.png"));
BASE_OBJECTS["DOME"]=DOME_DECAL;
LoadMap("map1");
return true;
}
bool GetAnyKey() {
switch (GAME_STATE) {
case CUTSCENE_1:{
if (textInd>=STORY_TEXT1.length()) {
fadeOut();
}
}break;
}
}
bool OnUserUpdate(float fElapsedTime) override
{
elapsedTime+=fElapsedTime;
while (elapsedTime>TARGET_RATE) {
elapsedTime-=TARGET_RATE;
updateGame();
}
if (!CUTSCENE_ACTIVE) {
if (GetKey(olc::D).bHeld||GetKey(olc::RIGHT).bHeld) {
PLAYER_COORDS[0]=clamp(PLAYER_COORDS[0]+MOVE_SPD,0.0,(double)MAP_WIDTH);
}
if (GetKey(olc::A).bHeld||GetKey(olc::LEFT).bHeld) {
PLAYER_COORDS[0]=clamp(PLAYER_COORDS[0]-MOVE_SPD,0.0,(double)MAP_WIDTH);
}
if (GetKey(olc::W).bHeld||GetKey(olc::UP).bHeld) {
PLAYER_COORDS[1]=clamp(PLAYER_COORDS[1]-MOVE_SPD,0.0,(double)MAP_HEIGHT);
}
if (GetKey(olc::S).bHeld||GetKey(olc::DOWN).bHeld) {
PLAYER_COORDS[1]=clamp(PLAYER_COORDS[1]+MOVE_SPD,0.0,(double)MAP_HEIGHT);
}
}
drawGame();
// called once per frame
return true;
}
void fadeOutCompleted() {
switch (GAME_STATE) {
case CUTSCENE_1:{
GAME_STATE=CUTSCENE_2;
PlayCutscene(PAN_DOME);
fadeIn();
}break;
}
}
void fadeInCompleted() {
}
void PlayCutscene(CUTSCENE scene) {
switch (scene) {
case PAN_DOME:{
PLAYER_COORDS[0]=14;
PLAYER_COORDS[1]=18+(64/2/32);
}break;
}
for (int i=0;i<8;i++) {
CUTSCENE_FLAGS[i]=false;
}
CUTSCENE_ACTIVE=true;
CUTSCENE_TIMER=0;
}
void updateGame(){
frameCount++;
if (CUTSCENE_ACTIVE) {
CUTSCENE_TIMER++;
}
if (fade&&transparency<255) {
transparency=clamp(transparency+FADE_SPD,0,255);
if (transparency==255) {
fadeOutCompleted();
}
} else
if (!fade&&transparency>0) {
transparency=clamp(transparency-FADE_SPD,0,255);
if (transparency==0) {
fadeInCompleted();
}
}
switch (GAME_STATE) {
case CUTSCENE_1:{
if (textInd<STORY_TEXT1.length()) {
char c = STORY_TEXT1[textInd++];
CUTSCENE_CONSOLE_TEXT+=c;
if (c!='\n') {
cursorX++;
} else {
cursorX=0;
}
if (GetTextSize(CUTSCENE_CONSOLE_TEXT).x>WIDTH-32) {
int tempIndex=textInd;
while (CUTSCENE_CONSOLE_TEXT[--tempIndex]!=' ') {
CUTSCENE_CONSOLE_TEXT.erase(tempIndex);
cursorX--;
}
CUTSCENE_CONSOLE_TEXT.erase(tempIndex++);
CUTSCENE_CONSOLE_TEXT+='\n';
cursorX=0;
while (tempIndex<textInd) {
CUTSCENE_CONSOLE_TEXT+=STORY_TEXT1[tempIndex++];
cursorX++;
}
}
}
}break;
case CUTSCENE_2:{
//FLAG 0 - When flipped on, camera stops.
if (!CUTSCENE_FLAGS[0]) {
PLAYER_COORDS[0]+=0.06;
} else {
if (CUTSCENE_TIMER>120) {
fadeOut();
}
}
if (PLAYER_COORDS[0]>38+(128/2/32)) {
PLAYER_COORDS[0]=38+(128/2/32);
CUTSCENE_FLAGS[0]=true;
CUTSCENE_TIMER=0;
}
}break;
}
}
void drawGame(){
switch (GAME_STATE) {
case CUTSCENE_1:{
DrawStringDecal({16,16},CUTSCENE_CONSOLE_TEXT,olc::GREEN,{1,1});
if (textInd<STORY_TEXT1.length()) {
FillRectDecal({16+(cursorX)*8%(WIDTH-32),8+GetTextSize(CUTSCENE_CONSOLE_TEXT).y+((cursorX==28)?8:0)},{4,8},olc::GREEN);
} else {
FillRectDecal({16+(cursorX)*8%(WIDTH-32),8+GetTextSize(CUTSCENE_CONSOLE_TEXT).y+((cursorX==28)?8:0)},{4,8},olc::Pixel(0,255,0,(0.5*sin(frameCount*4/60.0)+0.5)*256));
}
GradientFillRectDecal({0,0},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1});
GradientFillRectDecal({WIDTH/2,0},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1});
GradientFillRectDecal({0,HEIGHT/2},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2});
GradientFillRectDecal({WIDTH/2,HEIGHT/2},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1});
}break;
case CUTSCENE_2:
case GAMEWORLD:{
DrawGameWorld();
}break;
}
FillRectDecal({0,0},{WIDTH,HEIGHT},olc::Pixel(0,0,0,transparency));
}
void DrawGameWorld() {
for (int y=-1;y<=HEIGHT/32;y++) {
for (int x=-1;x<=WIDTH/32;x++) {
int xOffset=PLAYER_COORDS[0]-(WIDTH/64);
int yOffset=PLAYER_COORDS[1]-(HEIGHT/64);
if (xOffset+x>=0&&xOffset+x<MAP_WIDTH&&yOffset+y>=0&&yOffset+y<MAP_HEIGHT) {
DrawPartialDecal({(x-(PLAYER_COORDS[0]-(int)PLAYER_COORDS[0]))*32,(y-(PLAYER_COORDS[1]-(int)PLAYER_COORDS[1]))*32},{32,32},TILES,{0,0},{32,32},TILE_COLORS[MAP[yOffset+y][xOffset+x]]);
}
}
}
for (auto&obj:OBJECTS) {
DrawDecal({(obj.x-PLAYER_COORDS[0])*32+WIDTH/2,(obj.y-PLAYER_COORDS[1])*32+HEIGHT/2},obj.spr);
}
}
void fadeOut() {
fade=true;
}
void fadeIn() {
fade=false;
}
};
int main()
{
SeasonsOfLoneliness demo;
if (demo.Construct(256, 224, 4, 4))
demo.Start();
return 0;
}