Racing with any key press functionality

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
This commit is contained in:
sigonasr2 2022-10-10 21:08:25 -05:00
parent b7a2846c9d
commit fce9280b0b
5 changed files with 849 additions and 47 deletions

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

827
main.cpp
View File

@ -1,40 +1,815 @@
#include <memory> //--------------------------------------------------------------------------------------------------
#include <stdio.h> // F4 Racing
//--------------------------------------------------------------------------------------------------
// This is an advancement in my game making skills, building off the back of my work on the "Collect the Balls" game.
//--------------------------------------------------------------------------------------------------
// created by Rune
// black box code by Sigonasr2 from the OLC (one lone coder) Discord server
//--------------------------------------------------------------------------------------------------
#define OLC_PGE_APPLICATION
#include "pixelGameEngine.h" // used for drawing the game
class C2{ //--------------------------------------------------------------------------------------------------
// class
//--------------------------------------------------------------------------------------------------
class Racer : public olc::PixelGameEngine
{
public: public:
int data=4; Racer()
~C2(){ {
printf("C2 destroyed\n"); sAppName = "F4 Racing";
} }
private:
float car_pos = 0.0f;
float distance = 0.0f;
float speed = 0.0f;
float curvature = 0.0f;
float track_curve = 0.0f;
float car_curve = 0.0f;
float track_dist = 0.0f;
float cur_lap_time = 0.0f;
std::vector<std::pair<float, float>> vecTrack;
std::list<float> list_times;
bool bothKeysPressed = false; // checking for dual key press; could probably work with more than 2 keys
// custom control template
olc::Key Move_Up = olc::W;
olc::Key Move_Down = olc::S;
olc::Key Move_Left = olc::A;
olc::Key Move_Right = olc::D;
std::array<std::string, 4> keyslist = { "UP", "DOWN", "LEFT", "RIGHT" };
int configKeyIndex = -1;
char pressedKey;
public:
// Menu Setup
//----------------------------------------
bool activeOption = true; // highlighting current option
int highlighted;
struct MenuItem
{
std::string label; // label
olc::vi2d pos; // label's position
std::string label2; //Another label. To the right of label.
}; };
class C1{ struct Object
public: {
~C1(){ olc::vf2d pos{ 0, 0 }; // the x position represents how far to the left/right it is from the center. -1 ~ 1: road's range; the y position is how far along the track it is
printf("C1 destroyed\n"); olc::vf2d size{ 1, 1 };
olc::Decal* decal = nullptr;
olc::vf2d offset{ 0, 0 }; // how far off the image will be
bool rendered = false;
olc::vf2d drawPos;
olc::vf2d drawSize;
olc::vf2d drawOffsetPos;
};
std::vector<MenuItem> mainMenu;
std::vector<MenuItem> playGame;
std::vector<MenuItem> pickTrack;
std::vector<MenuItem> grandPrix;
std::vector<MenuItem> selectCar;
std::vector<MenuItem> controls;
std::vector<std::string> gameOver;
std::vector<Object> gameObjects;
enum class state
{
MAIN_MENU,
PLAY_GAME,
CAR_SELECT,
CONTROLS,
RUN_GAME,
// game
TRACK_SELECT,
CUP_SELECT,
// tracks
CIRCUIT,
FIG_EIGHT,
ARROW_HEAD,
track_4,
OVERPASS,
track_5,
track_6,
track_7,
track_8,
track_9,
JX9, // special track ;)
// cups
INDIE,
STREET,
PRO,
GRAND_PRIX
};
state gameState = state::MAIN_MENU;
// Variables
//----------------------------------------
// lap times
// player
int score; // score at end of track; based on final place
int lap; // current lap player is on
int place; // current place player is in
olc::Decal* car; // initialize car
olc::Decal* hill; // initialize hill
olc::Decal* grass; // initialize grass
olc::Decal* road; // initialize road, curbs, and finish line
olc::Decal* banner; // initialize banner
olc::Decal* title; // initialize title banner
std::string KeyToString(olc::Key key) {
const std::array<std::string,98> keyStrings = {"NONE","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2","3","4","5","6","7","8","9","F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12","UP","DOWN","LEFT","RIGHT","SPACE","TAB","SHIFT","CTRL","INS","DEL","HOME","END","PGUP","PGDN","BACK","ESCAPE","ENTER","ENTER","PAUSE","SCROLL LK","NUMPAD0","NUMPAD1","NUMPAD2","NUMPAD3","NUMPAD4","NUMPAD5","NUMPAD6","NUMPAD7","NUMPAD8","NUMPAD9","NUMPAD*","NUMPAD/","NUMPAD+","NUMPAD-","NUMPAD.",".","=",",","-","OEM_1","OEM_2","OEM_3","OEM_4","OEM_5","OEM_6","OEM_7","OEM_8","CAPS LOCK","END"};
return keyStrings[key];
} }
void PrintData(std::weak_ptr<C2>ptr) {
printf("Data is %d\n",ptr.lock()->data); //--------------------------------------------------------------------------------------------------
// Create Game Objects
//--------------------------------------------------------------------------------------------------
bool OnUserCreate() override
{
mainMenu = // show menu options
{
{ "START GAME", { ScreenWidth() / 2, ScreenHeight() / 5 * 3} },
{ "CONTROLS", { ScreenWidth() / 2, ScreenHeight() / 5 * 3 + 64} },
{ "QUIT", {ScreenWidth() / 2, ScreenHeight() / 5 * 3 + 128 } }
};
playGame =
{
{ "TRACK SELECTION", { ScreenWidth() / 2, ScreenHeight() / 4 } },
{ "GRAND PRIX", { ScreenWidth() / 2, ScreenHeight() / 2 } },
{ "BACK", { ScreenWidth() / 2, ScreenHeight() / 4 * 3} }
};
pickTrack = // show track options
{
{ "CIRCUIT", { ScreenWidth() / 4, ScreenHeight() / 4 } },
{ "INFINITY", { ScreenWidth() / 2, ScreenHeight() / 4 } },
{ "ARROWHEAD", { ScreenWidth() / 4 * 3, ScreenHeight() / 4 } },
{"Track 4", { ScreenWidth() / 4, ScreenHeight() / 2 }},
{ "OVERPASS", { ScreenWidth() / 2, ScreenHeight() / 2 } },
{"Track 6", { ScreenWidth() / 4 * 3, ScreenHeight() / 2 } } ,
{"Track 7", { ScreenWidth() / 4, ScreenHeight() / 4 * 3 } },
{"Track 8", { ScreenWidth() / 2, ScreenHeight() / 4 * 3 } },
{"Track 9", { ScreenWidth() / 4 * 3, ScreenHeight() / 4 * 3 } }
};
grandPrix = // show race cups
{
{ "INDIE CUP", { ScreenWidth() / 3, ScreenHeight() / 3 } },
{ "STREET CUP", { ScreenWidth() / 3 * 2, ScreenHeight() / 3 } },
{ "PRO CUP", { ScreenWidth() / 3, ScreenHeight() / 3 * 2 } },
{ "GRAND PRIX", { ScreenWidth() / 3 * 2, ScreenHeight() / 3 * 2 } },
{ "BACK", { ScreenWidth() / 2, ScreenHeight() / 6 * 5 } }
};
selectCar = // pick a color
{
{ "RED", { ScreenWidth() / 5, ScreenHeight() / 3 } },
{ "BLUE", { ScreenWidth() / 5 * 2, ScreenHeight() / 3 } },
{ "GREEN", { ScreenWidth() / 5 * 3, ScreenHeight() / 3 } },
{ "GOLD", { ScreenWidth() / 5 * 4, ScreenHeight() / 3 } },
{ "PURPLE", { ScreenWidth() / 5, ScreenHeight() / 3 * 2 } },
{ "WHITE", { ScreenWidth() / 5 * 2, ScreenHeight() / 3 * 2 } },
{ "ORANGE", { ScreenWidth() / 5 * 3, ScreenHeight() / 3 * 2 } },
{ "BLACK", { ScreenWidth() / 5 * 4, ScreenHeight() / 3 * 2 } }
};
controls =
{
{ "FORWARD", { ScreenWidth() / 3, 64 },KeyToString(Move_Up) },
{ "BACK", { ScreenWidth() / 3, 64 + 64 },KeyToString(Move_Down) },
{ "LEFT", { ScreenWidth() / 3, 64 + 128 },KeyToString(Move_Left) },
{ "RIGHT", { ScreenWidth() / 3, 64 + 192 },KeyToString(Move_Right) }
};
gameOver = { "Return to Main Menu" };
//----------------------------------------
car = new olc::Decal(new olc::Sprite("art/car.png")); // load car
hill = new olc::Decal(new olc::Sprite("art/hills.png"), false, false); // load hill
grass = new olc::Decal(new olc::Sprite("art/grass.png"), false, false); // load grass
road = new olc::Decal(new olc::Sprite("art/road.png"), false, false); // load road, curbs, and finish line
banner = new olc::Decal(new olc::Sprite("art/start.png"), false, false); // load banner
title = new olc::Decal(new olc::Sprite("art/title.png")); // load title banner
// JX9 track layout
vecTrack.push_back(std::make_pair(0.0f, 10.0f)); // start/finish line
vecTrack.push_back(std::make_pair(0.0f, 200.0f)); // straight
vecTrack.push_back(std::make_pair(1.0f, 200.0f)); // sharp right
vecTrack.push_back(std::make_pair(0.0f, 400.0f)); // long straight
vecTrack.push_back(std::make_pair(-1.0f, 100.0f)); // soft left
vecTrack.push_back(std::make_pair(0.0f, 200.0f)); // straight
vecTrack.push_back(std::make_pair(-1.0f, 200.0f)); // sharp left
vecTrack.push_back(std::make_pair(1.0f, 200.0f)); // sharp right
vecTrack.push_back(std::make_pair(0.0, 200.0f)); // straight
vecTrack.push_back(std::make_pair(0.2f, 500.0f)); // gradual right
vecTrack.push_back(std::make_pair(0.0f, 200.0f)); // straight
for (auto t : vecTrack)
{
track_dist += t.second;
}
distance = track_dist - 100;
list_times = { 0,0,0,0,0 };
gameObjects.push_back({ /*{-1.5,track_dist - 50}, {10,6}, {0,240}*/ });
return true;
}
//--------------------------------------------------------------------------------------------------
// reset game
//--------------------------------------------------------------------------------------------------
void Reset()
{
car_pos = 0.0f;
distance = 0.0f;
speed = 0.0f;
curvature = 0.0f;
track_curve = 0.0f;
car_curve = 0.0f;
//track_dist = 0.0f; will need to be moved elsewhere; the game will calculate *ALL* track sizes at the start, and then simply use the appropriate numbers when loading each track on request
cur_lap_time = 0.0f;
// Note: the following all need to be reset during the process, when they've been implemented
// -player position (on screen)
// -player position (on track)
// -track section
// -all lap times
// -score
//
// if called from other parts of the program, other than the 'F1' key, it should be resetting to the menu
// the 'F1' key is meant to reset the player on the current track they're on
//
}
//--------------------------------------------------------------------------------------------------
// main menu
//--------------------------------------------------------------------------------------------------
void DisplayMenu(std::vector<MenuItem> list, bool horizontal = false)
{
// drawing and coloring menu selections
for (int i = 0; i < list.size(); i++)
{
olc::vi2d textSize = GetTextSize(list[i].label) / 2 * 4;
olc::Pixel textCol = olc::GREY; // greys out unselected options
if (highlighted == i)
{
textCol = olc::Pixel(255, 201, 14); // gold
}
DrawStringDecal(list[i].pos - textSize, list[i].label, textCol, { 4.0f, 4.0f });
if (list[i].label2.size()>0) {
olc::vi2d offset = {256,-textSize.y/2};
DrawStringDecal(list[i].pos + offset, list[i].label2, textCol, { 4.0f, 4.0f });
}
}
// selecting options
highlighted = std::clamp(highlighted, 0, (int)list.size() - 1); // loop if out of range
if (!horizontal)
{
// vertical controls
if (GetKey(olc::Key::W).bPressed || GetKey(olc::Key::UP).bPressed)
{
highlighted--; // up
}
if (GetKey(olc::Key::S).bPressed || GetKey(olc::Key::DOWN).bPressed)
{
highlighted++; // down
}
}
else
{
if (GetKey(olc::Key::A).bPressed || GetKey(olc::Key::LEFT).bPressed)
{
highlighted--; // left
}
if (GetKey(olc::Key::D).bPressed || GetKey(olc::Key::RIGHT).bPressed)
{
highlighted++; // right
}
}
if (highlighted >= (int)list.size())
{
highlighted = 0; // wrap around when above max
}
if (highlighted < 0)
{
highlighted = list.size() - 1; // wrap around when below zero
}
}
void GetAnyKeyPress(olc::Key keypress) override{
if (configKeyIndex!=-1) {
switch (configKeyIndex) {
case 0:{
Move_Up=keypress;
}break;
case 1:{
Move_Down=keypress;
}break;
case 2:{
Move_Left=keypress;
}break;
case 3:{
Move_Right=keypress;
}break;
}
controls[configKeyIndex].label2=KeyToString(keypress);
configKeyIndex=-1;
}
}
//--------------------------------------------------------------------------------------------------
// Main Game Function
//--------------------------------------------------------------------------------------------------
bool OnUserUpdate(float fElapsedTime) override
{
if (GetKey(olc::Key::CTRL).bHeld && GetKey(olc::Key::F12).bHeld && !bothKeysPressed)
{
return false;
}
// dry skybox
GradientFillRectDecal({ 0.0f, 0.0f }, { ScreenWidth() + 0.0f, ScreenHeight() / 2 + 0.0f }, olc::DARK_BLUE, olc::BLUE, olc::BLUE, olc::DARK_BLUE);
// the hills have eyes; y'know, like in Super Mario Bros. What reference did you think was going to be here?
DrawPartialDecal({ 0.0f, ScreenHeight() / 2 - 100.0f }, hill, { 0.0f + track_curve * 200, 0.0f }, { ScreenWidth() + 0.0f, (float)hill->sprite->height }, { 1.5f, 1.0f });
//DrawPartialDecal({ 180.0f, ScreenHeight() / 2 - 100.0f }, hill, { 0.0f + track_curve * 200, 0.0f }, { ScreenWidth() + 0.0f, (float)hill->sprite->height });
// draw grass
DrawPartialWarpedDecal(grass, { { 0.0f, ScreenHeight() / 2 + 0.0f }, { -ScreenWidth() * 2 + 0.0f, ScreenHeight() + 0.0f}, { ScreenWidth() * 2 + ScreenWidth() + 0.0f, ScreenHeight() + 0.0f }, { ScreenWidth() + 0.0f, ScreenHeight() / 2 + 0.0f } }, { 0.0f, -distance }, { 1 * 32, 4 * 64 });
//--------------------------------------------------------------------------------------------------
if (gameState == state::MAIN_MENU)
{
DrawStringDecal({0,0},std::string(1,pressedKey),olc::WHITE,{3,3});
// display title
DrawDecal({ 95.5f, 95.5f }, title/*, {0.4f, 0.4f}*/);
DisplayMenu(mainMenu);
//DrawStringDecal({ ScreenWidth() / 2 + 0.0f, ScreenHeight() / 2 + 0.0f }, "START GAME", olc::WHITE, { 4.0f, 4.0f });
if (GetKey(olc::Key::ENTER).bPressed || GetKey(olc::Key::SPACE).bPressed)
{
// vertical menu
if (highlighted == 0)
{
gameState = state::PLAY_GAME;
highlighted = 0;
}
else if (highlighted == 1)
{
gameState = state::CONTROLS;
highlighted = 0;
}
else
{
return false; // quit game
}
}
if (GetKey(olc::Key::ESCAPE).bPressed)
{
return false; // exit via Escape key
}
}
//--------------------------------------------------------------------------------------------------
else if (gameState == state::PLAY_GAME)
{
DisplayMenu(playGame);
if (GetKey(olc::Key::ENTER).bPressed || GetKey(olc::Key::SPACE).bPressed)
{
// vertical menu
if (highlighted == 0)
{
gameState = state::TRACK_SELECT;
highlighted = 0;
}
else if (highlighted == 1)
{
gameState = state::CUP_SELECT;
highlighted = 0;
}
else
{
gameState = state::MAIN_MENU; // return to menu
highlighted = 0;
}
}
if (GetKey(olc::Key::ESCAPE).bPressed || GetKey(olc::Key::BACK).bPressed)
{
gameState = state::MAIN_MENU;
highlighted = 0;
}
}
//--------------------------------------------------------------------------------------------------
else if (gameState == state::TRACK_SELECT)
{
DisplayMenu(pickTrack);
if (GetKey(olc::Key::ENTER).bPressed || GetKey(olc::Key::SPACE).bPressed)
{
if (highlighted == 0)
{
gameState = state::CIRCUIT;
gameState = state::CAR_SELECT;
}
else if (highlighted == 1)
{
gameState = state::FIG_EIGHT;
gameState = state::CAR_SELECT;
}
else if (highlighted == 2)
{
gameState = state::ARROW_HEAD;
gameState = state::CAR_SELECT;
}
else if (highlighted == 3)
{
gameState = state::track_4;
gameState = state::CAR_SELECT;
}
else if (highlighted == 4)
{
gameState = state::OVERPASS;
gameState = state::CAR_SELECT;
}
else if (highlighted == 5)
{
gameState = state::track_5;
gameState = state::CAR_SELECT;
}
else if (highlighted == 6)
{
gameState = state::track_6;
gameState = state::CAR_SELECT;
}
else if (highlighted == 7)
{
gameState = state::track_7;
gameState = state::CAR_SELECT;
}
else if (highlighted == 8)
{
gameState = state::track_8;
gameState = state::CAR_SELECT;
}
//else
else
{
// return to previous screen, in this instance it should change according to whether the player
// came down via the Cup selection screen, or the Track selection screen
}
}
if (GetKey(olc::Key::CTRL).bHeld && GetKey(olc::Key::F9).bHeld)
{
// okay, so, gotta work out how to do cheat codes it seems xD
gameState = state::JX9;
gameState = state::CAR_SELECT;
}
if (GetKey(olc::Key::ESCAPE).bPressed || GetKey(olc::Key::BACK).bPressed)
{
gameState = state::PLAY_GAME;
highlighted = 0;
}
}
//--------------------------------------------------------------------------------------------------
else if (gameState == state::CUP_SELECT)
{
DisplayMenu(grandPrix);
if (GetKey(olc::Key::ENTER).bPressed || GetKey(olc::Key::SPACE).bPressed)
{
// 2 x 2 menu
if (highlighted == 0)
{
gameState = state::INDIE;
gameState = state::CAR_SELECT;
}
else if (highlighted == 1)
{
gameState = state::STREET;
gameState = state::CAR_SELECT;
}
else if (highlighted == 2)
{
gameState = state::PRO;
gameState = state::CAR_SELECT;
}
else if (highlighted == 3)
{
gameState = state::GRAND_PRIX;
gameState = state::CAR_SELECT;
}
else
{
gameState = state::PLAY_GAME; // return to menu
highlighted = 0;
}
}
if (GetKey(olc::Key::ESCAPE).bPressed || GetKey(olc::Key::BACK).bPressed)
{
gameState = state::PLAY_GAME;
highlighted = 0;
}
}
//--------------------------------------------------------------------------------------------------
else if (gameState == state::CAR_SELECT)
{
DisplayMenu(selectCar);
if (GetKey(olc::Key::ESCAPE).bPressed || GetKey(olc::Key::BACK).bPressed)
{
// needs to go to previous screen
// previous screen may be:
// -Cup Select
// -Track Select
}
}
//--------------------------------------------------------------------------------------------------
else if (gameState == state::CONTROLS)
{
DisplayMenu(controls);
if (GetKey(olc::Key::ENTER).bPressed)
{
if (highlighted == 0)
{
configKeyIndex=highlighted;
}
else if (highlighted == 1)
{
configKeyIndex=highlighted;
}
else if (highlighted == 2)
{
configKeyIndex=highlighted;
}
else if (highlighted == 3)
{
configKeyIndex=highlighted;
}
else
{
gameState = state::MAIN_MENU;
highlighted = 0;
}
}
if (GetKey(olc::Key::ESCAPE).bPressed || GetKey(olc::Key::BACK).bPressed)
{
gameState = state::MAIN_MENU;
}
}
//--------------------------------------------------------------------------------------------------
else // run main game loop
{
Clear(olc::BLACK); // this still needed? we've since replaced it with the gradient sky box
// get a point on the track
float offset = 0;
int TrackSection = 0;
cur_lap_time += fElapsedTime;
// record lap time
if (distance >= track_dist)
{
distance -= track_dist;
list_times.push_front(cur_lap_time); // push time to front
list_times.pop_back(); // pop time to back
cur_lap_time = 0.0f;
}
// find position on track (could optimize) << should probably optimize given the complexity of this game
while (TrackSection < vecTrack.size() && offset <= distance)
{
offset += vecTrack[TrackSection].second;
TrackSection++;
}
float TargetCurvature = vecTrack[TrackSection - 1].first; // drawing curves to screen
float TrackCurveDiff = (TargetCurvature - curvature) * fElapsedTime * speed; // correcting the drawing of curves to the screen
curvature += TrackCurveDiff; // update track curve difference
track_curve += (curvature)*fElapsedTime * speed;
// draw racetrack canvas
std::vector<olc::vf2d> pos;
std::vector<olc::vf2d> uvs;
for (int y = 0; y < ScreenHeight() / 2; y++)
{
// racetrack canvas variables
float perspective = (float)y / (ScreenHeight() / 2.0f);
float mid_point = 0.5f + curvature * powf((1.0f - perspective), 3);
float road_width = 0.1f + perspective * 0.8f;
float curb_width = road_width * 0.15f;
road_width *= 0.5f;
int lf_curb = (mid_point - road_width) * ScreenWidth();
int rt_curb = (mid_point + road_width) * ScreenWidth();
int row = ScreenHeight() / 2 + y;
float horizon = powf(1.0f - perspective, 2) * 80;
// check for finish line
if (distance + horizon > track_dist - 20 && distance + horizon < track_dist)
{
// draw checkerboard pattern
uvs.push_back({ 0, (float)fmod(((distance + horizon) - (track_dist - 20)) / 20.0f, 0.5f) + 0.5f });
uvs.push_back({ 1, (float)fmod(((distance + horizon) - (track_dist - 20)) / 20.0f, 0.5f) + 0.5f });
}
else
{
// draw standard track piece
uvs.push_back({ 0, sinf(80.0f * powf(1.0f - perspective, 2) + distance) / 4 + 0.25f });
uvs.push_back({ 1, sinf(80.0f * powf(1.0f - perspective, 2) + distance) / 4 + 0.25f });
}
// drawing grass and curb
pos.push_back({ lf_curb + 0.0f, row + 0.0f });
pos.push_back({ rt_curb + 0.0f, row + 0.0f });
// black box rendering shenanigans; if I ever understand programming enough at a later date, I can figure out wtf is going on here
int i = 0;
for (Object& obj : gameObjects)
{
float horizonRange = powf(1.0f - perspective, 2) * ((distance + horizon) - obj.pos.y) / horizon;
if (!obj.rendered && (distance + horizon) > obj.pos.y && (distance + horizon) < obj.pos.y + 80 && row >= ScreenHeight() / 2 + ScreenHeight() / 2 * horizonRange)
{
obj.drawPos = { (mid_point + road_width * obj.pos.x) * ScreenWidth(), horizonRange * (ScreenHeight() / 2) + ScreenHeight() / 2 };
obj.drawOffsetPos = { obj.offset.x, obj.size.y * road_width * -obj.offset.y };
obj.drawSize = { obj.size.x * road_width, obj.size.y * road_width };
obj.rendered = true;
// yeah.... so, even after copying it manually, i still have no clue what this thing is doing, lol
}
}
}
// on the road again; drawing the track
SetDecalStructure(olc::DecalStructure::STRIP);
DrawPolygonDecal(road, pos, uvs);
SetDecalStructure(olc::DecalStructure::FAN);
// draw trackside props
for (Object& obj : gameObjects)
{
if (obj.rendered)
{
if (obj.decal != nullptr)
{
DrawDecal(obj.drawPos + obj.drawOffsetPos, obj.decal, obj.drawSize);
}
else
{
FillRectDecal(obj.drawPos, obj.drawSize, olc::BLUE);
}
}
}
//----------------------------------------
// debug quick-reset
if (GetKey(olc::Key::F4).bPressed)
{
Reset();
}
// move forward
if (GetKey(olc::Key::W).bHeld || GetKey(olc::Key::UP).bHeld)
{
speed += 2.0f * fElapsedTime;
}
else // might remove this in a later stage of development
{
speed -= 1.0f * fElapsedTime;
}
// move back ?
if (GetKey(olc::Key::S).bHeld || GetKey(olc::Key::DOWN).bHeld)
{
distance -= 20.0f * fElapsedTime;
}
int car_dir = 0; // default car facing
// move left
if (GetKey(olc::Key::A).bHeld || GetKey(olc::Key::LEFT).bHeld)
{
car_curve -= 0.7f * fElapsedTime;
car_dir = -1;
}
// move right
if (GetKey(olc::Key::D).bHeld || GetKey(olc::Key::RIGHT).bHeld)
{
car_curve += 0.7f * fElapsedTime;
car_dir = +1;
}
// slow car if on grass
if (fabs(car_curve - track_curve) >= 0.8f)
{
speed -= 5.0f * fElapsedTime;
}
// clamp speed
if (speed < 0.0f) speed = 0.0f;
if (speed > 1.0f) speed = 1.0f;
// move car along track according to car speed
distance += (70.0f * speed) * fElapsedTime;
// draw car
car_pos = car_curve - track_curve;
DrawDecal({ ScreenWidth() / 2 - 128 + car_pos * ScreenWidth() / 2, ScreenHeight() / 4 * 3.0f - 128 }, car);
SetPixelMode(olc::Pixel::ALPHA);
// spedometer
std::string mph = std::to_string(speed);
DrawString(4, 4, mph);
// show time
auto disp_time = [](float t)
{
int min = t / 60.0f;
int sec = t - (min * 60.0f);
int milli = (t - (float)sec) * 1000.0f;
// need to change this out to a 'DrawString()' function instead
return std::to_string(min) + "." + std::to_string(sec) + ":" + std::to_string(milli);
};
// correct for the first '0' in the seconds timer
//if ()
//{
// // draw min + '0' + sec + milli
// DrawString(4, 16, disp_time(cur_lap_time));
//}
//else
//{
DrawString(4, 16, disp_time(cur_lap_time));
//}
// display last 5 lap times
int j = 30;
for (auto l : list_times)
{
DrawString(10, j, disp_time(l));
j += 10;
}
// debug code
//std::string numb1 = std::to_string(car_pos);
//DrawString(4, 26, numb1);
//std::string numb2 = std::to_string(track_dist);
//DrawString(4, 38, numb2);
}
return true;
} }
}; };
int main(){ //--------------------------------------------------------------------------------------------------
std::shared_ptr<C1> ptrA{std::make_shared<C1>()}; int main()
{
Racer game;
if (game.Construct(1280, 720, 1, 1))
game.Start();
std::weak_ptr<C1>ptrA_2=ptrA; return 0;
if (!ptrA_2.expired()) {
printf("Count:%ld",ptrA.use_count());
std::shared_ptr<C1> ptrA_3{ptrA};
printf("Inside if statement.\n");
std::shared_ptr<C2> ptrB{std::make_shared<C2>()};
ptrA_2.lock()->PrintData(ptrB);
printf("Count:%ld",ptrA.use_count());
} }
printf("Count:%ld",ptrA.use_count());
printf("Outside if statement.\n");
return -1; //--------------------------------------------------------------------------------------------------
} // END OF FILE
//--------------------------------------------------------------------------------------------------

View File

@ -928,6 +928,8 @@ namespace olc
virtual bool OnUserUpdate(float fElapsedTime); virtual bool OnUserUpdate(float fElapsedTime);
// Called once on application termination, so you can be one clean coder // Called once on application termination, so you can be one clean coder
virtual bool OnUserDestroy(); virtual bool OnUserDestroy();
virtual void GetAnyKey();
virtual void GetAnyKeyPress(olc::Key pressedKey);
// Called when a text entry is confirmed with "enter" key // Called when a text entry is confirmed with "enter" key
virtual void OnTextEntryComplete(const std::string& sText); virtual void OnTextEntryComplete(const std::string& sText);
@ -1084,6 +1086,7 @@ namespace olc
// Draws a line in Decal Space // Draws a line in Decal Space
void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE); void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE);
void DrawRectDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE);
void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
void DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
// Clears entire draw target to Pixel // Clears entire draw target to Pixel
@ -1149,6 +1152,7 @@ namespace olc
#endif #endif
public: // Branding public: // Branding
std::string sAppName; std::string sAppName;
Renderable fontRenderable;
private: // Inner mysterious workings private: // Inner mysterious workings
olc::Sprite* pDrawTarget = nullptr; olc::Sprite* pDrawTarget = nullptr;
@ -1176,7 +1180,6 @@ namespace olc
int nFrameCount = 0; int nFrameCount = 0;
bool showFPS = true; bool showFPS = true;
bool bSuspendTextureTransfer = false; bool bSuspendTextureTransfer = false;
Renderable fontRenderable;
std::vector<LayerDesc> vLayers; std::vector<LayerDesc> vLayers;
uint8_t nTargetLayer = 0; uint8_t nTargetLayer = 0;
uint32_t nLastFPS = 0; uint32_t nLastFPS = 0;
@ -2686,6 +2689,13 @@ namespace olc
vLayers[nTargetLayer].vecDecalInstance.push_back(di); vLayers[nTargetLayer].vecDecalInstance.push_back(di);
} }
void PixelGameEngine::DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col) {
DrawLineDecal(pos,{pos.x+size.x,pos.y},col);
DrawLineDecal({pos.x,pos.y},{pos.x,pos.y+size.y},col);
DrawLineDecal({pos.x,pos.y+size.y},{pos.x+size.x,pos.y+size.y},col);
DrawLineDecal({pos.x+size.x,pos.y},{pos.x+size.x,pos.y+size.y},col);
}
void PixelGameEngine::FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col) void PixelGameEngine::FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col)
{ {
olc::vf2d vNewSize = (size - olc::vf2d(0.375f, 0.375f)).ceil(); olc::vf2d vNewSize = (size - olc::vf2d(0.375f, 0.375f)).ceil();
@ -3200,6 +3210,7 @@ namespace olc
bool PixelGameEngine::IsTextEntryEnabled() const bool PixelGameEngine::IsTextEntryEnabled() const
{ return bTextEntryEnable; } { return bTextEntryEnable; }
void PixelGameEngine::SetFPSDisplay(bool display) void PixelGameEngine::SetFPSDisplay(bool display)
{ showFPS=display; } { showFPS=display; }
@ -3294,6 +3305,9 @@ namespace olc
bool PixelGameEngine::OnUserDestroy() bool PixelGameEngine::OnUserDestroy()
{ return true; } { return true; }
void PixelGameEngine::GetAnyKey(){};
void PixelGameEngine::GetAnyKeyPress(olc::Key pressedKey){};
void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); } void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); }
bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; } bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; }
@ -3439,8 +3453,10 @@ namespace olc
platform->HandleSystemEvent(); platform->HandleSystemEvent();
// Compare hardware input states from previous frame // Compare hardware input states from previous frame
auto ScanHardware = [&](HWButton* pKeys, bool* pStateOld, bool* pStateNew, uint32_t nKeyCount) auto ScanHardware = [&](HWButton* pKeys, bool* pStateOld, bool* pStateNew, uint32_t nKeyCount,bool keyboard=true)
{ {
bool pressed=false;
int key;
for (uint32_t i = 0; i < nKeyCount; i++) for (uint32_t i = 0; i < nKeyCount; i++)
{ {
pKeys[i].bPressed = false; pKeys[i].bPressed = false;
@ -3449,6 +3465,8 @@ namespace olc
{ {
if (pStateNew[i]) if (pStateNew[i])
{ {
pressed=true;
key=i;
pKeys[i].bPressed = !pKeys[i].bHeld; pKeys[i].bPressed = !pKeys[i].bHeld;
pKeys[i].bHeld = true; pKeys[i].bHeld = true;
} }
@ -3457,13 +3475,17 @@ namespace olc
pKeys[i].bReleased = true; pKeys[i].bReleased = true;
pKeys[i].bHeld = false; pKeys[i].bHeld = false;
} }
GetAnyKey();
} }
pStateOld[i] = pStateNew[i]; pStateOld[i] = pStateNew[i];
} }
if (pressed) {
if (keyboard) {GetAnyKeyPress((olc::Key)key);}
else {GetAnyKeyPress(olc::Key::NONE);}}
}; };
ScanHardware(pKeyboardState, pKeyOldState, pKeyNewState, 256); ScanHardware(pKeyboardState, pKeyOldState, pKeyNewState, 256);
ScanHardware(pMouseState, pMouseOldState, pMouseNewState, nMouseButtons); ScanHardware(pMouseState, pMouseOldState, pMouseNewState, nMouseButtons,false);
// Cache mouse coordinates so they remain consistent during frame // Cache mouse coordinates so they remain consistent during frame
vMousePos = vMousePosCache; vMousePos = vMousePosCache;
@ -3533,6 +3555,7 @@ namespace olc
// Present Graphics to screen // Present Graphics to screen
renderer->DisplayFrame(); renderer->DisplayFrame();
if (showFPS) {
// Update Title Bar // Update Title Bar
fFrameTimer += fElapsedTime; fFrameTimer += fElapsedTime;
nFrameCount++; nFrameCount++;
@ -3540,10 +3563,14 @@ namespace olc
{ {
nLastFPS = nFrameCount; nLastFPS = nFrameCount;
fFrameTimer -= 1.0f; fFrameTimer -= 1.0f;
std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName + ((showFPS)?" - FPS: " + std::to_string(nFrameCount):""); std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName + " - FPS: " + std::to_string(nFrameCount);
platform->SetWindowTitle(sTitle); platform->SetWindowTitle(sTitle);
nFrameCount = 0; nFrameCount = 0;
} }
} else {
std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName;
platform->SetWindowTitle(sTitle);
}
} }
void PixelGameEngine::olc_ConstructFontSheet() void PixelGameEngine::olc_ConstructFontSheet()