Learn SDL 2
Tôi đã sử dụng Raylib, SFML, và hôm nay là SDL. Tôi đã mua 1 khoá học về SDL2 C++ programming trên Udemy để tiếp tục học cách làm game và kết hợp học C++.
2 Get-to-Class¶
Tạo một class có các functions là set input và display
#include <iostream>
using namespace std;
class Point2D
{
public:
Point2D();
~Point2D();
void Set(int dx, int dy);
void Display();
---
title: Learn-SDL2
date: 2022-04-11
tags:
- template
---
Created date: 2022-04-11
## Learn-SDL2
private:
int mX{};
int mY{};
};
Point2D::Point2D()
{
}
Point2D::~Point2D()
{
}
void Point2D::Set(int dx, int dy)
{
mX = dx;
mY = dy;
}
void Point2D::Display()
{
cout << "X: " << mX << ", Y: " << mY << endl;
}
int main()
{
Point2D point1; // Sử dụng class Point2D vừa tạo
Point2D point2;
point1.Set(10, 20);
point1.Display();
point2.Set(100, 200);
point2.Display();
return 0;
}
2.1 Private and Publics¶
Sử dụng private để các function không thể access được như các function trong publics. ví dụ như point1.mX
thì sẽ gây ra lỗi.
2.2 Encapsulation - vật chứa¶
Bởi vì các private variable
thì hidden bởi các class, nó không thể truy cập được, nó chỉ có thể Display nếu chúng ta tạo các functions để display nó như Display()
2.3 Data members¶
cout << "Size of Point1 is:" << sizeof(point1) << endl;
Sử dụng sizeof
để biết size của nó
2.4 Methods¶
Đây còn gọi là các functions ví dụ như
2.5 Struct vs Class¶
- Struct khi khai báo luôn là
public
- Class cần phải khai báo
public
hayprivate
nếu không toàn bộ đều làprivate
Tạo một Struct để get input và Display
struct StructPoint2D
{
void Set(int dx, int dy);//khai báo function Set cho StructPoint2D
void Display();
int mX; // Sử dụng Struct thì không có Private, tất cả đều Public
int mY;
};
Định nghĩa functions
void StructPoint2D::Set(int dx, int dy) // định nghĩa Struct Set
{
mX = dx;
mY = dy;
}
void StructPoint2D::Display()
{
cout << "Struct X= " << mX << " Y= " << mY << endl;
}
2.6 Constructor¶
Name của một class được gọi là constructor
Một class chỉ có 1 constructor, đây là nơi để khai báo thuộc tính thường được sử dụng của class này, được định nghĩa như sau
Lưu ý các mX và mY là các variables trong private
. Vì vậy thay vì sử dụng function Set(x, y)
thì bây giờ chỉ cần sử dụng constructor
để khai báo là được rồi. Khi tạo các variable dựa theo class
thì nó sẽ có các tính năng cơ bản nhất trong constructor
Bây giờ khi khai báo thì không cần dùng function Set
nữa mà sử dụng như sau
Cũng có thể khai báo là
point1 = {10,20};
2.7 Initializer lists¶
Khi khai báo constructor nếu cần có các giá trị mặc định thì có thể khai báo cùng 1 hàng
Tính năng này hữu ích khi sử dụng reference, nó sẽ không bị lỗi trong các class. Nếu chỉ khai báo trong body thì reference chưa tồn tại vì vậy cần dùng initilizer.
Cần chú ý đến thứ tự của mX và mY khi được khai báo trong private
2.8 Delegate constructor - Uỷ quyền¶
2.9 Destructor¶
Nếu cần free các resources trong class thì cần sử dụng destructor
2.10 Class scope¶
2.11 Explicit constructor¶
Có thể tạo nhiều constructor với cùng tên method trong một class. Ví dụ như
class Point2D
{
public:
Point2D(int x, int y); // Name của class được gọi là constructor
Point2D(float x, float y); // constructor thứ 2 với cùng tên nhưng khác argument
void Set(int dx, int dy);
void Display();
int GetX();
int GetY();
Để gán sử dụng đúng constructor thì khai báo explicit
trước method đó
2.12 Call methods on objects¶
Để gọi một method từ object vừa được tạo theo class thì sử dụng dấu chấm .
VD như khai báo
Point2D point1(10, 20); // Sử dụng class Point2D vừa tạo
Point2D point2 = { 100,200 }; // cách khai báo khác là {x,y}
point1.Display();
point2.Display();
Sử dụng new Constructor
Point2D* pPoint = new Point2D(); // Point2D nhưng thuộc pointer
pPoint->Display(); // vì pPoint là pointer thì phải dùng ->, nếu không phải để là (*pPoint).Display()
2.13 Objects with objects in 2 functions¶
class Point2D
{
public:
Point2D() {}; //constructor nhưng k có argument
Point2D(int x, int y) :mX{ x }, mY{ y }// Name của class được gọi là constructor
{
}
~Point2D() {};
void Display()
{
cout << "Class X: " << mX << ", Y: " << mY << endl;
}
void SetValue(int dx, int dy)// methods thì không thể dùng initializer như constructor được
{
mX = dx;
mY = dy;
}
private:
int mX{}; //{} để initialize variable này
int mY{};
};
class secondPoint2D
{
public:
secondPoint2D() :myPoint2D(20, 10)//constructor này dựa theo dữ liệu của constructor Point2D
{
};
~secondPoint2D() {};
void SetValue(int dx, int dy)// methods thì không thể dùng initializer như constructor được
{
mX = dx;
mY = dy;
}
void Display()
{
cout << "Class X: " << mX << ", Y: " << mY << endl;
}
private:
int mX{}; //{} để initialize variable này
int mY{};
Point2D myPoint2D{};
};
2.14 Array of objects¶
Ví dụ như khai báo một array từ class MyClass myClass[5];
nhưng sẽ gây lỗi vì không hiểu đây là 1 array. Cần phải khai báo mảng #include <vector>
Bây giờ thì khai báo myClass thuộc một mảng Vector có dạng là MyClass vector<MyClass> myClass[5];
2.15 Copy constructor¶
Có thể tạo 1 function độc lập và dùng Class là argument, sau đó có thể truy vấn các functions trong class đó
void MyFunc(MyClass myClass) // 1 function độc lập sử dụng MyClass, nhưng không thuộc Class này
{
myClass.Display();
}
2.16 Static keywords¶
Khi static
được đứng trước variables hoặc một function thì giá trị của nó không thể thay đổi. Giá trị nó tính lifetime
trong suốt chương trình, vì vậy nó chỉ được gọi duy nhất 1 lần.
static
có ích khi cần lưu lại kết quả của lần chạy đầu tiên
static có thể bên trong hoặc ngoài functions
2.17 Constant¶
constant của function
2.18 inline methods¶
In fact, all the functions defined inside the class are implicitly inline
2.19 friend keyword¶
Khi sử dụng friend
trước một variable trong private
của một class thì cho phép class đó sử dụng các variable private
class Node {
private:
int key;
Node* next;
/* Other members of Node Class */
// Now class LinkedList can
// access private members of Node
friend class LinkedList;
};
Ví dụ như code sau của header file
class Vector2D
{
public:
Vector2D() :Vector2D(0, 0) {}
Vector2D(float x, float y) :mX(x), mY(y) {}
void SetX(float x) { mX = x; }
void SetY(float y) { mY = y; }
float GetX() { return mX; }
float GetY() { return mY; }
friend ostream& operator <<(ostream& consoleOut, const Vector2D& vec); // sử dụng friend để có thể truy cập được private variables
private:
float mX, mY;
};
Trong cpp definition file
#include "Vector2D.h"
ostream& operator<<(ostream& consoleOut, const Vector2D& vec)
{
cout << "X: " << vec.mX << ", Y: " << vec.mY << endl;
}
3 Math in C++¶
3.1 Comparing floats¶
Vì các floats có rất nhiều số sau dấu phẩy. Ví dụ không thể so sánh 3.14==PI
được. Có thể tạo một function đơn giản để so sánh hai giá trị floats.
Sử dụng thêm cmath
lib để tính toán
3.2 Negating a vector¶
Sử dụng unary overloading operator.
Như trong class Vector2D mà tôi tự tạo thì sẽ có float x và float y. Trong python thì chúng ta có thể sử dụng vector1+ vector2 một cách đơn giản, nó sẽ tự x1+x1 và y1 + y2 để tạo ra vector mới. Nhưng C++ thì chưa hiểu functions này. Vì vậy cần sử dụng unary overloading operator.
Khi sử dụng overide operator, conpiler sẽ dịch ra như sau
p1+p2 tương đương p1.operator+(p2). Tức là operator+()
là một function của class, còn p2 là một argument của function này.
Xem ví dụ sau
#pragma once
#include <iostream>
using namespace std;
class Vector2D
{
public:
Vector2D() :Vector2D(0, 0) {}
Vector2D(float x, float y) :mX(x), mY(y) {}
void SetX(float x) { mX = x; }
void SetY(float y) { mY = y; }
float GetX() { return mX; }
float GetY() { return mY; }
friend ostream& operator <<(ostream& consoleOut, const Vector2D& vec); // sử dụng friend để có thể truy cập được private variables
bool operator==(const Vector2D& vec2) const;
bool operator!=(const Vector2D& vec2) const;
Vector2D operator-() const; // tạo một operator based on class Vector2 ngay trong class này
// cần phải sử dụng const để nó không thay đổi variable bên trong function
private:
float mX, mY;
};
Một lưu ý nhỏ trong class này là const member function
. Đoạn code dưới đây giải thích ý nghĩa sử dụng const cho functions.
const
đặt cuối function tức là promise
sẽ KHÔNG đổi values của this*
class Fred {
public:
void inspect() const; // This member promises NOT to change *this
void mutate(); // This member function might change *this
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
changeable.inspect(); // Okay: doesn't change a changeable object
changeable.mutate(); // Okay: changes a changeable object
unchangeable.inspect(); // Okay: doesn't change an unchangeable object
unchangeable.mutate(); // ERROR: attempt to change unchangeable object
}
Một ví dụ khác
#include <cassert> // dùng thay cho ifdefine
#include <cmath>
Vector2D Vector2D::operator/(float scale) const
{
assert(fabsf(scale) > EPSILON); // kiểm trả scale không phải là zero, để không chia cho 0
return Vector2D(this->mX/scale, this->mX/scale);
}
Trong ví dụ này có sử dụng thêm assert
, đây là dùng để test điều kiện trước khi thực hiện các lệnh phía sau. Điều này khá giống với một hàm if
??
Điểm khác biệt với if
là assert
chỉ sử dụng khi debug để biết lỗi hay không. Còn khi release sẽ không check nó, giúp build nhanh hơn so với hàm if
.
Một điều lưu ý khác là vị trí của operator, nó có thể là x*n nhưng cũng có thể là n*x
Vector2D Vector2D::operator*(float scale) const
{
return Vector2D(scale*this->mX, scale*this->mY);
}
Vector2D operator*(float scalar, const Vector2D& vec)
{
return vec * scalar;
}
4 SDL2¶
4.1 SDL window¶
Khi cài SDL2 từ vcpkg cần phải manually link lib với linker của VS2019.
`$(VcpkgRoot)\installed$(VcpkgTriplet)\debug\lib\manual-link\SDL2maind.lib
Ngoài ra trong main()
cũng cần khai báo như sau, vì SDL main() function trùng với nó
Hoặc phải dùng
#define SDL_MAIN_HANDLED
hàng đầu tiên của cpp có liên quan đến SDL2. Trong main function cần bổ sung thêm 4.2 Screen and Surface SDL¶
In PixelFormat của Surface
Backlinks¶
The following pages link to this page:
Created : Apr 4, 2022
Recent Posts
- 2024-11-02: BUỔI 10 - Phân tích thị trường
- 2024-11-02: BUỔI 11 - Phân tích thị trường
- 2024-11-02: BUỔI 12 - Phân tích sóng tăng
- 2024-11-02: BUỔI 13 - Phân tích hỏi đáp
- 2024-11-02: BUỔI 14 - Yếu tố kiểm soát
- 2024-11-02: BUỔI 15 - Hỏi đáp
- 2024-11-01: BUỔI 6 - Ôn lại và bổ sung
- 2024-11-01: BUỔI 7 - Chiến thuật Trend
- 2024-11-01: BUỔI 8 - Công thức điểm vào lệnh
- 2024-11-01: K2023 - BUỔI 9 - Quy trình vào lệnh