Racing with any key press functionality

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
master
sigonasr2 2 years ago
parent b7a2846c9d
commit fce9280b0b
  1. BIN
      C++ProjectTemplate
  2. 2
      C++ProjectTemplate.js
  3. BIN
      C++ProjectTemplate.wasm
  4. 837
      main.cpp
  5. 55
      pixelGameEngine.h

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

@ -1,40 +1,815 @@
#include <memory>
#include <stdio.h>
class C2{
public:
int data=4;
~C2(){
printf("C2 destroyed\n");
}
};
//--------------------------------------------------------------------------------------------------
// 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 C1{
public:
~C1(){
printf("C1 destroyed\n");
//--------------------------------------------------------------------------------------------------
// class
//--------------------------------------------------------------------------------------------------
class Racer : public olc::PixelGameEngine
{
public:
Racer()
{
sAppName = "F4 Racing";
}
void PrintData(std::weak_ptr<C2>ptr) {
printf("Data is %d\n",ptr.lock()->data);
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.
};
struct Object
{
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
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];
}
};
//--------------------------------------------------------------------------------------------------
// 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 } }
};
int main(){
std::shared_ptr<C1> ptrA{std::make_shared<C1>()};
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 } }
};
std::weak_ptr<C1>ptrA_2=ptrA;
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());
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;
}
printf("Count:%ld",ptrA.use_count());
printf("Outside if statement.\n");
//--------------------------------------------------------------------------------------------------
// reset game
//--------------------------------------------------------------------------------------------------
return -1;
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()
{
Racer game;
if (game.Construct(1280, 720, 1, 1))
game.Start();
return 0;
}
//--------------------------------------------------------------------------------------------------
// END OF FILE
//--------------------------------------------------------------------------------------------------

@ -928,6 +928,8 @@ namespace olc
virtual bool OnUserUpdate(float fElapsedTime);
// Called once on application termination, so you can be one clean coder
virtual bool OnUserDestroy();
virtual void GetAnyKey();
virtual void GetAnyKeyPress(olc::Key pressedKey);
// Called when a text entry is confirmed with "enter" key
virtual void OnTextEntryComplete(const std::string& sText);
@ -1084,6 +1086,7 @@ namespace olc
// Draws a line in Decal Space
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 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
@ -1149,6 +1152,7 @@ namespace olc
#endif
public: // Branding
std::string sAppName;
Renderable fontRenderable;
private: // Inner mysterious workings
olc::Sprite* pDrawTarget = nullptr;
@ -1173,10 +1177,9 @@ namespace olc
bool bEnableVSYNC = false;
float fFrameTimer = 1.0f;
float fLastElapsed = 0.0f;
int nFrameCount = 0;
bool showFPS = true;
int nFrameCount = 0;
bool showFPS = true;
bool bSuspendTextureTransfer = false;
Renderable fontRenderable;
std::vector<LayerDesc> vLayers;
uint8_t nTargetLayer = 0;
uint32_t nLastFPS = 0;
@ -2686,6 +2689,13 @@ namespace olc
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)
{
olc::vf2d vNewSize = (size - olc::vf2d(0.375f, 0.375f)).ceil();
@ -3200,6 +3210,7 @@ namespace olc
bool PixelGameEngine::IsTextEntryEnabled() const
{ return bTextEntryEnable; }
void PixelGameEngine::SetFPSDisplay(bool display)
{ showFPS=display; }
@ -3294,6 +3305,9 @@ namespace olc
bool PixelGameEngine::OnUserDestroy()
{ return true; }
void PixelGameEngine::GetAnyKey(){};
void PixelGameEngine::GetAnyKeyPress(olc::Key pressedKey){};
void PixelGameEngine::OnTextEntryComplete(const std::string& sText) { UNUSED(sText); }
bool PixelGameEngine::OnConsoleCommand(const std::string& sCommand) { UNUSED(sCommand); return false; }
@ -3439,8 +3453,10 @@ namespace olc
platform->HandleSystemEvent();
// 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++)
{
pKeys[i].bPressed = false;
@ -3449,6 +3465,8 @@ namespace olc
{
if (pStateNew[i])
{
pressed=true;
key=i;
pKeys[i].bPressed = !pKeys[i].bHeld;
pKeys[i].bHeld = true;
}
@ -3457,13 +3475,17 @@ namespace olc
pKeys[i].bReleased = true;
pKeys[i].bHeld = false;
}
GetAnyKey();
}
pStateOld[i] = pStateNew[i];
}
if (pressed) {
if (keyboard) {GetAnyKeyPress((olc::Key)key);}
else {GetAnyKeyPress(olc::Key::NONE);}}
};
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
vMousePos = vMousePosCache;
@ -3533,16 +3555,21 @@ namespace olc
// Present Graphics to screen
renderer->DisplayFrame();
// Update Title Bar
fFrameTimer += fElapsedTime;
nFrameCount++;
if (fFrameTimer >= 1.0f)
{
nLastFPS = nFrameCount;
fFrameTimer -= 1.0f;
std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName + ((showFPS)?" - FPS: " + std::to_string(nFrameCount):"");
if (showFPS) {
// Update Title Bar
fFrameTimer += fElapsedTime;
nFrameCount++;
if (fFrameTimer >= 1.0f)
{
nLastFPS = nFrameCount;
fFrameTimer -= 1.0f;
std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName + " - FPS: " + std::to_string(nFrameCount);
platform->SetWindowTitle(sTitle);
nFrameCount = 0;
}
} else {
std::string sTitle = "OneLoneCoder.com - Pixel Game Engine - " + sAppName;
platform->SetWindowTitle(sTitle);
nFrameCount = 0;
}
}

Loading…
Cancel
Save