I used the Pong-Tutorial "Template" and changed the code for the platformer. Here is the C++ for AppGameKit Tier 2
// Includes
#include "agkGame.h"
#include "Paddle.h"
#include "Ball.h"
#include "Score.h"
// Namespace
using namespace AGK;
class AGK_Platformer // not needed, because olcGameEngine still has a Main() method.
{
};
app App;
uString sLevel;
int nLevelWidth;
int nLevelHeight;
float fPlayerPosX = 0.0f;
float fPlayerPosY = 0.0f;
float fPlayerVelX = 0.0f;
float fPlayerVelY = 0.0f;
bool bPlayerOnGround = false;
float fCameraPosX = 0.0f;
float fCameraPosY = 0.0f;
int cyan;
int red;
int green;
void app::Begin(void) // OnUserCreate()
{
agk::SetVirtualResolution(1280, 720);
agk::SetWindowSize(1280, 720, 0);
//agk::SetWindowPosition(100, 100);
//agk::SetWindowAllowResize(1);
agk::SetClearColor(25, 25, 25);
agk::SetSyncRate(300, 0);
agk::SetScissor(0, 0, 0, 0);
agk::SetWindowTitle("Tile Based Platform Game");
nLevelWidth = 64;
nLevelHeight = 16;
//-------------123456789x123456789x123456789x123456789x123456789x123456789x1234
sLevel.Append("................................................................"); // 1
sLevel.Append("......ooooooo..................................................."); // 2
sLevel.Append("........oooo...................................................."); // 3
sLevel.Append("..........o....................................................."); // 4
sLevel.Append("......#...............########.................................."); // 5
sLevel.Append(".....................##....................#.#.................."); // 6
sLevel.Append("...................###.....................#.#.................."); // 7
sLevel.Append("..................####.........................................."); // 8
sLevel.Append("##################################.###############.........#####"); // 9
sLevel.Append(".................................#.#....................###....."); //10
sLevel.Append(".........................########..#.................###........"); // 1
sLevel.Append(".........................#.........#..............###..........."); // 2
sLevel.Append(".........................#.#############.......###.............."); // 3
sLevel.Append(".........................#..................###................."); // 4
sLevel.Append(".........................#####################.................."); // 5
sLevel.Append("................................................................"); // 6
cyan = agk::MakeColor(0, 250, 250);
red = agk::MakeColor(250, 0, 0);
green = agk::MakeColor(0, 250, 0);
/*
game_state = Game_State::START_SCREEN;
agk::SetWindowAllowResize(0);
agk::SetWindowTitle("FolkisA RPG");
unsigned int const net = agk::LoadSprite("media/net.png");
agk::SetSpritePositionByOffset(net, agk::GetVirtualWidth() / 2.0f, agk::GetVirtualHeight() / 2.0f);
unsigned int const paddle_image = agk::LoadImage("media/paddle.png");
static float const PADDLE_DISTANCE_FROM_EDGE = 20.0f;
float const player_x = (agk::GetImageWidth(paddle_image) / 2.0f) + PADDLE_DISTANCE_FROM_EDGE;
float const ai_x = (agk::GetVirtualWidth() - (agk::GetImageWidth(paddle_image) / 2.0f)) - PADDLE_DISTANCE_FROM_EDGE;
player_paddle = new Paddle(paddle_image, player_x);
ai_paddle = new Paddle(paddle_image, ai_x);
ball = new Ball(player_paddle, ai_paddle);
unsigned int font = agk::LoadFont("media/kongtext.ttf");
player_score = new Score(font, agk::GetVirtualWidth() * 0.2f);
ai_score = new Score(font, agk::GetVirtualWidth() * 0.8f);
result_text = agk::CreateText("");
agk::SetTextAlignment(result_text, 1);
agk::SetTextFont(result_text, font);
agk::SetTextSize(result_text, 30.0f);
agk::SetTextPosition(result_text, agk::GetVirtualWidth() / 2.0f, agk::GetVirtualHeight() * 0.3f);
agk::SetTextVisible(result_text, 0);
next_screen_text = agk::CreateText("Press Space To Start");
agk::SetTextAlignment(next_screen_text, 1);
agk::SetTextFont(next_screen_text, font);
agk::SetTextSize(next_screen_text, 20.0f);
agk::SetTextPosition(next_screen_text, agk::GetVirtualWidth() / 2.0f, agk::GetVirtualHeight() * 0.5f);
*/
}
int app::Loop(void) // OnUserUpdate
{
/*
switch (game_state) {
case Game_State::START_SCREEN: {
update_start_screen();
} break;
case Game_State::GAME_SCREEN: {
update_game_screen();
} break;
case Game_State::RESULT_SCREEN: {
update_result_screen();
} break;
}
*/
agk::Print("Hallo");
// Utility Lambdas
auto GetTile = [&](int x, int y)
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
return sLevel[y * nLevelWidth + x];
else
return ' ';
};
auto SetTile = [&](int x, int y, wchar_t c)
{
if (x >= 0 && x < nLevelWidth && y >= 0 && y < nLevelHeight)
{
sLevel.DeleteCharAt(y * nLevelWidth + x);
sLevel.InsertUnicodeAt(y * nLevelWidth + x, c);
}
};
// Draw Level
int nTileWidth = 64;
int nTileHeight = 64;
int nVisibleTilesX = agk::GetVirtualWidth() / nTileWidth;
int nVisibleTilesY = agk::GetVirtualHeight() / nTileHeight;
// Calculate Top-Leftmost visable tile
float fOffsetX = fCameraPosX - (float)nVisibleTilesX / 2.0f;
float fOffsetY = fCameraPosY - (float)nVisibleTilesY / 2.0f;
// Clamp camera to game boundaries
if (fOffsetX < 0) fOffsetX = 0;
if (fOffsetY < 0) fOffsetY = 0;
if (fOffsetX > nLevelWidth - nVisibleTilesX) fOffsetX = nLevelWidth - nVisibleTilesX;
if (fOffsetY > nLevelHeight - nVisibleTilesY) fOffsetY = nLevelHeight - nVisibleTilesY;
//fPlayerVelX = 0.0f;
//fPlayerVelY = 0.0f;
// Handle Input
if (1==1) // IsFocused() is Window in focus like GetEditBoxHasFocus ( index )
{
if (agk::GetRawKeyState(VK_UP))
{
fPlayerVelY = -6.0f;
}
if (agk::GetRawKeyState(VK_DOWN))
{
fPlayerVelY = 6.0f;
}
if (agk::GetRawKeyState(VK_RIGHT))
{
fPlayerVelX += (bPlayerOnGround ? 6.0f : 4.0f) * agk::GetFrameTime();
}
if (agk::GetRawKeyState(VK_LEFT))
{
fPlayerVelX += (bPlayerOnGround ? -6.0f:-4.0f) * agk::GetFrameTime();
}
if (agk::GetRawKeyPressed(VK_SPACE))
{
if (fPlayerVelY == 0)
{
fPlayerVelY = -12.0f;
}
}
}
fPlayerVelY += 20.0f * agk::GetFrameTime();
if (bPlayerOnGround)
{
fPlayerVelX += -3.0f * fPlayerVelX * agk::GetFrameTime();
if (fabs(fPlayerVelX) < 0.01f)
fPlayerVelX = 0.0f;
}
if (fPlayerVelX > 10.0f)
fPlayerVelX = 10.0f;
if (fPlayerVelX < -10.0f)
fPlayerVelX = -10.0f;
if (fPlayerVelY > 100.0f)
fPlayerVelY = 100.0f;
if (fPlayerVelY < -100.0f)
fPlayerVelY = -100.0f;
float fNewPlayerPosX = fPlayerPosX + fPlayerVelX * agk::GetFrameTime(); // fElapsedTime;
float fNewPlayerPosY = fPlayerPosY + fPlayerVelY * agk::GetFrameTime(); // fElapsedTime;
// Check for pickups!
if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f) == 'o')
SetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f, '.');
if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f) == 'o')
SetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 1.0f, '.');
if (GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f) == 'o')
SetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 0.0f, '.');
if (GetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f) == 'o')
SetTile(fNewPlayerPosX + 1.0f, fNewPlayerPosY + 1.0f, '.');
// Collision
if (fPlayerVelX <= 0)
{
if (GetTile(fNewPlayerPosX + 0.0f, fPlayerPosY + 0.0f) != '.' || GetTile(fNewPlayerPosX + 0.0f, fPlayerPosY + 0.9f) != '.')
{
fNewPlayerPosX = (int)fNewPlayerPosX + 1;
fPlayerVelX = 0;
}
}
else
{
if (GetTile(fNewPlayerPosX + 1.0f, fPlayerPosY + 0.0f) != '.' || GetTile(fNewPlayerPosX + 1.0f, fPlayerPosY + 0.9f) != '.')
{
fNewPlayerPosX = (int)fNewPlayerPosX;
fPlayerVelX = 0;
}
}
bPlayerOnGround = false;
if (fPlayerVelY <= 0)
{
if (GetTile(fNewPlayerPosX + 0.0f, fNewPlayerPosY + 0.0f) != '.' || GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY + 0.0f) != '.')
{
fNewPlayerPosY = (int)fNewPlayerPosY + 1;
fPlayerVelY = 0;
}
}
else
{
if (GetTile(fNewPlayerPosX + .0f, fNewPlayerPosY + 1.0f) != '.' || GetTile(fNewPlayerPosX + 0.9f, fNewPlayerPosY + 1.0f) != '.')
{
fNewPlayerPosY = (int)fNewPlayerPosY;
fPlayerVelY = 0;
bPlayerOnGround = true;
}
}
fPlayerPosX = fNewPlayerPosX;
fPlayerPosY = fNewPlayerPosY;
fCameraPosX = fPlayerPosX;
fCameraPosY = fPlayerPosY;
// Get offsets for smooth movement
float fTileOffsetX = (fOffsetX - (int)fOffsetX) * nTileWidth;
float fTileOffsetY = (fOffsetY - (int)fOffsetY) * nTileHeight;
// Draw visible tile map
for (int x = -1; x < nVisibleTilesX+1; x++)
{
for (int y = -1; y < nVisibleTilesY+1; y++) // edge artefacts
{
wchar_t sTileID = GetTile(x+fOffsetX, y+fOffsetY);
switch (sTileID)
{
case '.':
agk::DrawBox(x * nTileWidth - fTileOffsetX, y * nTileHeight-fTileOffsetY, (x + 1) * nTileWidth - fTileOffsetX, (y + 1) * nTileHeight - fTileOffsetY, cyan, cyan, cyan, cyan, 1);
break;
case '#':
agk::DrawBox(x * nTileWidth- fTileOffsetX, y * nTileHeight - fTileOffsetY, (x + 1) * nTileWidth - fTileOffsetX, (y + 1) * nTileHeight - fTileOffsetY, red, red, red, red, 1);
break;
default:
;
}
}
}
// Draw Player
agk::DrawBox((fPlayerPosX-fOffsetX) * nTileWidth, (fPlayerPosY-fOffsetY)* nTileHeight, (fPlayerPosX-fOffsetX + 1)* nTileWidth, (fPlayerPosY-fOffsetY + 1)* nTileHeight, green, green, green, green, 1);
agk::Sync();
return 0; // return 1 to close app
}
void app::End(void)
{
}
void app::update_start_screen() {
if (agk::GetRawKeyPressed(AGK_KEY_SPACE)) {
agk::SetTextVisible(next_screen_text, 0);
game_state = Game_State::GAME_SCREEN;
}
}
void app::update_game_screen() {
if (agk::GetRawKeyPressed(AGK_KEY_SPACE)) {
game_state = Game_State::RESULT_SCREEN;
}
if (agk::GetRawKeyState(AGK_KEY_UP)) {
player_paddle->move_up();
}
if (agk::GetRawKeyState(AGK_KEY_DOWN)) {
player_paddle->move_down();
}
if (ball->get_y() < ai_paddle->get_y()) {
ai_paddle->move_up();
}
if (ball->get_y() > ai_paddle->get_y()) {
ai_paddle->move_down();
}
ball->update();
bool game_over = false;
if (ball->get_x() < 0.0f) {
ai_score->add_point();
ball->reset();
if (ai_score->has_winning_score()) {
agk::SetTextString(result_text, "AI Player Won!");
game_over = true;
}
}
if (ball->get_x() > agk::GetVirtualWidth()) {
player_score->add_point();
ball->reset();
if (player_score->has_winning_score()) {
agk::SetTextString(result_text, "Human Player Won!");
game_over = true;
}
}
if (game_over) {
agk::SetTextString(next_screen_text, "Press Space To Continue..");
agk::SetTextVisible(result_text, 1);
agk::SetTextVisible(next_screen_text, 1);
game_state = Game_State::RESULT_SCREEN;
}
}
void app::update_result_screen() {
if (agk::GetRawKeyPressed(AGK_KEY_SPACE)) {
player_score->reset();
ai_score->reset();
player_paddle->reset();
ai_paddle->reset();
agk::SetTextString(next_screen_text, "Press Space To Start");
agk::SetTextVisible(result_text, 0);
game_state = Game_State::START_SCREEN;
}
}
I renamed the cpp and h files to "agkGame", because "template" was not as nice.
credits to javidx9.
I also only commented the "pong-code", most of it is not in use. Also the methods for updating never called. There is no game_state and so on. Also the graphics and sounds are not in use. I wrote "Hello" to the screen to show that it works.
Coins are black. But you can collect them. They got not counted.