Anda di halaman 1dari 6

#define OLC_PGE_APPLICATION

#include "HeaderUtamaPoli.h"

using namespace olc;


using namespace std;

class ShapePolimorfisme : public PixelGameEngine


{
public:
ShapePolimorfisme()
{
// Nama Aplikasi
sAppName = "ShapePoli"; // sAppName dari header string
}

private:

// Variabel Pan dan Zoom


vf2d vOffset = { 0.0f, 0.0f };
vf2d vMulaiPan = { 0.0f, 0.0f };
float fSkala = 10.0f;
float fGrid = 1.0f;

// Konversi koordinat dari ruang dunia ke ruang layar


void DuniaKeLayar(const vf2d& v, int& nLayarX, int& nLayarY)
{
nLayarX = (int)((v.x - vOffset.x) * fSkala);
nLayarY = (int)((v.y - vOffset.y) * fSkala);
}

// Konversi koordinat dari ruang layar ke ruang dunia


void LayarKeDunia(int nLayarX, int nLayarY, vf2d& v)
{
v.x = (float)(nLayarX) / fSkala + vOffset.x;
v.y = (float)(nLayarY) / fSkala + vOffset.y;
}

// Penunjuk ke shape yang saat ini ditentukan oleh penempatan node


sShape* tempShape = nullptr;

// Daftar penunjuk ke semua shape yang telah digambar sejauh ini


list<sShape*> DaftarShape;

/* Penunjuk ke node yang saat ini dipilih. Node yang dipilih


mengikuti kursor mouse*/
sNode* NodeTerpilih = nullptr;

// "Menekan" lokasi mouse


vf2d vKursor = { 0, 0 };

/* CATATAN! Tidak ada contoh langsung dari garis, lingkaran,


kotak atau kurva, aplikasi hanya menyadari keberadaan shape
Ini kekuatan dari polimorfisme */

public:
bool SaatMembuat() override
{
// Konfigurasikan ruang dunia (0,0) menjadi tengah ruang layar
vOffset = { (float)(-LebarLayar() / 2) / fSkala, (float)(-TinggiLayar()
/ 2) / fSkala };
return true;
}

bool SaatPerbarui(float fWaktuBerulang) override


{
// Dapatkan lokasi mouse bingkai ini
vf2d vMouse = { (float)DapatMouseX(), (float)DapatMouseY() };

// Tangani pan dan zoom


if (DapatMouse(2).bDitekan)
{
vMulaiPan = vMouse;
}

if (DapatMouse(2).bDitahan)
{
vOffset -= (vMouse - vMulaiPan) / fSkala;
vMulaiPan = vMouse;
}

vf2d vMouseSebelumZoom;
LayarKeDunia((int)vMouse.x, (int)vMouse.y, vMouseSebelumZoom);

// Key untuk ZoomIn


if (DapatKey(Key::I).bDitekan || DapatRodaMouse() > 0)
{
fSkala *= 1.1f;
}

// Key untuk ZoomOut


if (DapatKey(Key::O).bDitekan || DapatRodaMouse() < 0)
{
fSkala *= 0.9f;
}

vf2d vMouseSetelahZoom;
LayarKeDunia((int)vMouse.x, (int)vMouse.y, vMouseSetelahZoom);
vOffset += (vMouseSebelumZoom - vMouseSetelahZoom); // Tidak merubah
posisi mouse saat zoom

// Arahkan kursor mouse ke interval kisi terdekat


vKursor.x = floorf((vMouseSetelahZoom.x + 0.5f) * fGrid); // fungsi
floorf dari header cmath
vKursor.y = floorf((vMouseSetelahZoom.y + 0.5f) * fGrid);

// Key untuk garis lurus


if (DapatKey(Key::G).bDitekan)
{
tempShape = new sGaris();

// Tempatkan node pertama


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);

// Dapatkan node kedua


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);
}

// Key untuk shape persegi


if (DapatKey(Key::P).bDitekan)
{
tempShape = new sPersegi();

// Tempatkan node pertama


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);

// Dapatkan node kedua


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);
}

// Key untuk shape lingkaran


if (DapatKey(Key::L).bDitekan)
{
// Buat shape baru/new sebagai "sementara"
tempShape = new sLingkaran();

// Tempatkan node pertama


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);

// Dapatkan node kedua


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);
}

// Key untuk gari lengkung


if (DapatKey(Key::T).bDitekan)
{
// Buat shape baru/new sebagai "sementara"
tempShape = new sKurva();

// Tempatkan node pertama


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);

// Dapatkan node kedua


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);
}

// Key untuk shape segitiga


if (DapatKey(Key::S).bDitekan)
{
// Buat shape baru/new sebagai "sementara"
tempShape = new sSegitiga();

// Tempatkan node pertama


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);

// Dapatkan node kedua


NodeTerpilih = tempShape->NodeBerikutnya(vKursor);
}

/* Cari node apa pun yang ada di bawah kursor,


pilih node itu untuk mengganti bentuk atau pun posisi*/
if (DapatKey(Key::M).bDitekan)
{
//NodeTerpilih = nullptr;
for (auto& shape : DaftarShape)
{
NodeTerpilih = shape->HitNode(vKursor);
if (NodeTerpilih != nullptr)
break;
}
}

/* Jika sebuah node dipilih, buat node tersebut mengikuti


kursor mouse dengan memperbarui posisinya*/
if (NodeTerpilih != nullptr)
{
NodeTerpilih->pos = vKursor;
}

/* Saat pengguna mengklik kiri untuk menempatkan node,


shape dapat berkembang hingga tidak memerlukan node lagi,
di mana titik itu selesai dan ditambahkan ke daftar shape yang sudah
selesai*/
if (DapatMouse(0).bDirilis)
{
if (tempShape != nullptr)
{
NodeTerpilih = tempShape->NodeBerikutnya(vKursor);
if (NodeTerpilih == nullptr)
{
tempShape->warna = PUTIH;
DaftarShape.push_back(tempShape); // fungsi push_back
ada di header list
tempShape = nullptr; // Terimakasih @howlevergreen
}

}
else
{
NodeTerpilih = nullptr;
}
}

// Berikan warna pada latar utama/layar bersih


Bersih(HITAM);

int sx, sy;


int ex, ey;

// Untuk menggambar dunia baik kiri atas maupun kanan bawah


vf2d vDuniaKiriAtas, vDuniaKananBawah;
LayarKeDunia(0, 0, vDuniaKiriAtas);
LayarKeDunia(LebarLayar(), TinggiLayar(), vDuniaKananBawah);

// Dapatkan nilai di luar batas layar


vDuniaKiriAtas.x = floor(vDuniaKiriAtas.x); // fungsi floor dari header
cmath
vDuniaKiriAtas.y = floor(vDuniaKiriAtas.y);
vDuniaKananBawah.x = ceil(vDuniaKananBawah.x); // fungsi ceil dari
header cmath
vDuniaKananBawah.y = ceil(vDuniaKananBawah.y);
// Gambaran titik titik grid untuk pertemuan koordinat
for (float x = vDuniaKiriAtas.x; x < vDuniaKananBawah.x; x += fGrid)
{
for (float y = vDuniaKiriAtas.y; y < vDuniaKananBawah.y; y +=
fGrid)
{
DuniaKeLayar({ x, y }, sx, sy);
Gambar(sx, sy, BIRU);
}
}

// Gambaran garis putus putus untuk koordinat y


DuniaKeLayar({ 0,vDuniaKiriAtas.y }, sx, sy);
DuniaKeLayar({ 0,vDuniaKananBawah.y }, ex, ey);
GambarGaris(sx, sy, ex, ey, PUTIH, 0xF0F0F0F0);

// Gambaran garis putus putus untuk koordinat x


DuniaKeLayar({ vDuniaKiriAtas.x,0 }, sx, sy);
DuniaKeLayar({ vDuniaKananBawah.x,0 }, ex, ey);
GambarGaris(sx, sy, ex, ey, PUTIH, 0xF0F0F0F0);

// Perbarui koefisien terjemahan shape agar shape terbentuk di interval


yang pas
sShape::fSkalaDunia = fSkala;
sShape::vOffsetDunia = vOffset;

// Gambar shape setelah ditentukan


/*for (auto& shape : DaftarShape)
{
shape->GambarPribadi(this);
shape->GambarNode(this);
}*/

// Gambar shape yang sedang ditentukan


if (tempShape != nullptr)
{
tempShape->GambarPribadi(this);
tempShape->GambarNode(this);
}

// Gambaran lingkaran putih untuk letak kursor


DuniaKeLayar(vKursor, sx, sy);
GambarLingkaran(sx, sy, 2, PUTIH);

// Gambaran Data Posisi Kursor maupun Keypress untuk perintah tertentu


GambarRangkaian(250, 10, "X =" + to_string(vKursor.x) + " Y =" +
to_string(vKursor.x), HIJAU, 1);
GambarRangkaian(10, 25, "L => LINGKARAN", MERAH, 1);
GambarRangkaian(850, 25, "PERSEGI <= P", MERAH, 1);
GambarRangkaian(420, 450,"S => SEGITIGA", MERAH, 1);
GambarRangkaian(10, 450, "T => GARIS LENGKUNG", MERAH, 1);
GambarRangkaian(815, 450,"GARIS LURUS <= G", MERAH, 1);
GambarRangkaian(500, 10, "MERUBAH NODE <= M", KUNING, 1);
GambarRangkaian(10, 230, "I => ZOOMIN", MAGENTA, 1);
GambarRangkaian(850, 230,"ZOOMOUT <= O", MAGENTA, 1);
return true;
}
};
int main()
{
ShapePolimorfisme Poli;
// 950 lebar layar, 480 tinggi layar, 1 ukuran pixel, false untuk layar
console tidak full
if (Poli.Membangun(950, 480, 1, 1, false))
Poli.Mulai();
return 0;
}

Anda mungkin juga menyukai