Game Programming Using C++ SDC
Game Programming Using C++ SDC
C++
SDC GPWC,
Faculty of Engineering and Technology (ITER)
SOA (Deemed to be) University, BBSR, Odisha
2025
1. CO1: write, compile and execute simple C++ programs to solve computational
problems.
2. CO2: become familiar with basic games using SFML and Visual Studio, implementing
sprites, animations, player inputs, and Heads-Up Display (HUD) elements.
3. CO3: implementing Game Mechanics and Physics like collision detection, pickups,
bullets, and sound effects while applying dynamic collision detection and basic physics
concepts.
4. CO4: develop advanced game features, such as zombie shooter games, using sprite
sheets, vertex arrays, texture management, and layering views.
5. CO5: apply advanced object-oriented programming concepts like inheritance,
polymorphism, and abstraction to improve code management and game scalability.
6. CO6: implement file I/O, sound effects, and refining the game's HUD and UI, while
optimizing performance using C++ references, pointers, and the Standard Template
Library (STL).
Course Structure
Grading Pattern
Course Curriculum
Assignment Submission
There will be Minimum 10 assignments which students have to submit each carrying 10
marks.
The students have to complete the assignment and upload the scanned copy of it in
shared google form along with the screenshot of the output.
At the end of the semester before the External Lab exam the students have to submit the
complete assignments in physical format.
Assignments are to be submitted within the given deadline failing to which 4 marks will
be deducted.
Students may be asked to redo in case any unfair means is observed.
Introduction to C++
Introduction to C++
C++ is a general-purpose, high-performance programming language that supports object-
oriented, procedural, and generic programming paradigms. It was developed by Bjarne
Stroustrup in 1979 as an extension of the C programming language, adding features
such as classes and object-oriented programming.
On the other hand, Object Oriented Programing (OOP) emphasizes objects, which
bundle data and behavior together. Key concepts in OOP include classes, objects,
inheritance, encapsulation, polymorphism, and abstraction. This approach allows better
data security by encapsulating data within objects and restricting access. OOP ensures
modularity through classes and objects, improving code reusability and scalability. It
closely maps to real-world entities, making it intuitive for designing complex applications.
OOP languages like Java, Python, and C++ are ideal for developing enterprise-level
software, games, and web applications.
Features of the Object Oriented programming
Class vs Structure
A structure is a user-defined data type that groups related variables (fields) together
under one name. It is a value type, typically used for creating lightweight objects that do
not require inheritance or complex behavior. Structures are designed to store and
manipulate simple data efficiently. They are often used in procedural and object-oriented
programming for small, self-contained data entities.
Explanation:
1. #include <iostream> : This is a preprocessor directive to include the Input/Output
stream library.
2. int main() : The starting point of the program. Every C++ program must have a
main() function.
3. The std namespace exists in the C++ Standard Library, which is part of the
compiler's implementation of the C++ language.
4. The :: operator in C++ is called the scope resolution operator. It is used to specify
the scope of a particular identifier, such as a variable, function, or class, when there
are multiple possible scopes.
5. cout is an instance of the ostream class defined in std namespace.
6. std::cout : Used to print output to the console.
7. The << operator in C++ is called the stream insertion operator when used with
output streams, such as std::cout . It is used to send data to the output stream for
display on the console.
8. "Hello, World!" : The message that will be displayed on the console.
9. endl is a function. However, it behaves like an object when used with std::cout
because it acts as an argument to the operator<< function. Specifically, operator<<
is overloaded to accept manipulators (like std::endl ).
10. std::endl : Ends the current line and flushes the output buffer.
11. return 0; : Indicates that the program executed successfully.
How to Run:
1. Save the code in a file with a .cpp extension (e.g., hello_world.cpp ).
2. Compile the program using a C++ compiler
Output
Hello, World!
Namespaces were introduced in C++ to solve the problem of name collisions in large
projects. Without namespaces, functions, variables, or classes with the same name in
different parts of the program or libraries would cause ambiguity and errors.
Advantages of Namespaces
1. Prevents Name Collisions: Avoids ambiguity when different parts of the program or
libraries define entities with the same name.
2. Improves Code Readability:Groups related entities logically under a meaningful
name.
3. Enhances Modularity: Encourages splitting large codebases into smaller,
independent modules.
4. Facilitates Library Design: Makes it easier to integrate multiple libraries into the
same project.
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
Standard Input and Output Stream
In C++, cin and cout are the standard input and output streams, respectively, provided
by the Standard Input/Output Library ( <iostream> ). They are used to perform basic
input and output operations in C++ programs.
Example
int main() {
cout << "Hello, World!" << endl; // Output message
cout << "The value of 5 + 3 is: " << 5 + 3 << endl; // Output
expression
return 0;
}
Output
Hello, World!
The value of 5 + 3 is: 8
Chaining Output
You can chain multiple outputs using the << operator. This makes the code concise and
expressive.
cout << "Name: " << "John Doe" << ", Age: " << 25 << endl;
Output
Name: John Doe, Age: 25
Formatting Output
To improve readability, you can format the output using manipulators from the
<iomanip> library:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double price = 123.456;
cout << fixed << setprecision(2); // Fixed-point with 2 decimals
cout << "Price: $" << price << endl;
cout << setw(10) << left << "Item" << setw(8) << right << "Price" <<
endl;
cout << setw(10) << left << "Book" << setw(8) << right << "$12.99" <<
endl;
return 0;
}
Output
Price: $123.46
Item Price
Book $12.99
Escape Sequences
Special characters can be displayed using escape sequences:
#include <iostream>
using namespace std;
int main() {
cout << "Newline: Hello\nWorld!\n";
cout << "Tab: Hello\tWorld!\t2025\n";
cout << "Backslash: This is \\ a backslash\n";
cout << "Double Quote: He said, \"Hi!\"\n";
cout << "Single Quote: It\'s sunny\n";
cout << "Alert: \a (may not work on all systems)\n";
cout << "Backspace: Hello\bWorld!\n";
cout << "Carriage Return: Hello\rWorld!\n";
cout << "Form Feed: Hello\fWorld!\n";
cout << "Vertical Tab: Hello\vWorld!\n";
cout << "Question Mark: Why is this here \?\n";
cout << "Null Character: This is\0null\n";
return 0;
}
Output
Newline: Hello
World!
Tab: Hello World! 2025
Backslash: This is \ a backslash
Double Quote: He said, "Hi!"
Single Quote: It's sunny
Alert: (may not work on all systems)
Backspace: HellWorld!
World!ge Return: Hello
Form Feed: Hello
World!
Vertical Tab: Hello
World!
Question Mark: Why is this here ?
Null Character: This is
Purpose: Used to take input from the user via the console (standard input).
Syntax: cin >> variable;
The >> operator, called the "extraction operator," extracts data from the input stream
and stores it in a variable.
It stops reading input when it encounters whitespace, a newline, or an EOF.
Chaining Input
You can use the >> operator multiple times to read multiple inputs in a single line.
int a, b, c;
cin >> a >> b >> c;
Handling Whitespace
#include <iostream>
using namespace std;
int main() {
char name[30];
cout << "Enter your full name: ";
cin.getline(name, 30); // Reads the entire line
cout << "Hello, " << name << "!" << endl;
return 0;
}
#include <iostream>
using namespace std;
int main() {
int age;
cout << "Enter your age: ";
cin >> age;
Output
Enter your age: q
Invalid input! Please enter a number.
Input Redirection ( < ): Reads input from a file instead of the keyboard.
Output Redirection ( > ): Writes output to a file instead of the console.
Example Program
Program: Read from Input, Write to Output
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
int age;
return 0;
}
John
30
Name: John
Age: 30
1. Default Behavior:
cin reads from the keyboard.
cout writes to the console.
2. With Redirection:
Input ( cin ) reads from the specified input file.
Output ( cout ) writes to the specified output file.
3. Overwrite vs Append:
> overwrites the file if it exists.
>> appends to the file without overwriting.
4. Error Redirection:
Redirect the standard error ( cerr ) to a file using 2> .
Example: ./program 2> error.txt
Data types simply refers to the type and size of data associated with variables and
functions.
The Following diagram shows types C++.
1. User-defined Types
Custom types defined by the programmer:
2. Built-in Types
Predefined primitive data types:
Integral Type
int – Integer numbers
char – Character data
Floating Type
float – Single-precision floating-point
double – Double-precision floating-point
Void
Represents absence of value, used in functions with no return.
b. char (Character)
double pi = 3.1415926535;
e. bool (Boolean)
Represents logical values: true or false .
Size: Usually 1 byte.
Example:
f. void
void displayMessage() {
cout << "Hello, World!";
}
3. Derived Types
Formed using built-in or user-defined types:
List of Modifiers
1. signed
2. unsigned
3. short
4. long
Note
In C++, derived data types are data types that are built from the fundamental (basic)
data types. They allow us to group basic data or refer to it in more complex ways.
Common derived types include arrays, functions, pointers, and references. These help
manage collections of data, reuse code, and manipulate memory efficiently in C++.
Arrays
An array is a collection of elements of the same type, stored one after another in
memory.
Example:
int numbers[3];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
cout << "The second element is " << numbers[1] << endl;
Arrays are data structures that store sets of data items under a single name declaration.
Each element of the array must be of the same type. When allocated, an array takes up a
contiguous block of memory. The elements can be accessed via an index (a non-negative
integer).
Declaring Arrays
An array is declared like any other variable ( <type> then <variable name> ) but also
included is the number of items in the array (the size must be specified when declaring an
array). When an array is declared, memory is allocated for the array, and it remains that
size. Each element is accessed by an index (or subscript), beginning with the zero-ith
element. So, for example, if you need to store a set of 5 integer grades, you can declare
an array like the following:
int grades[5];
where the array will have space for 5 integers indexed from 0-4: grades[0], grades[1],
grades[2], grades[3], & grades[4] each one can contain an integer. If you need to access
the 3rd item, you would access grades[2] or grades[n-1] where n is the total number of
elements in the array. In memory, you can picture it looking something like the following:
grades
0
1
2
3
4
Once allocated, this allows you to have one variable name for a set of same-type
items.
You can use the entire array as a single object, or each item in the array individually,
as shown below.
An individual array element can be used anywhere that a normal variable can be used.
For example, if you want to assign the 3rd element the value of 85, then you would write
grades[2] = 85;
grades
0
1
2 85
3
4
Or, if you have an integer variable called g5 and you want to assign to it the value of the
5th element (assuming it has a value), you would write
g5 = grades[4];
which then gives g5 the value of whatever that 5th element is in the array.
Arrays make it much easier for handling large data sets without having to declare each of
the items as individual variables. They also allow you to perform subtasks, like filling the
elements of an array from user input or a file, displaying all of the elements of an array in
forward or reverse order, sorting the values of an array in ascending or descending order,
determining the sum, average, or some other statistic from the array values, and finding
the highest or lowest value.
With a for loop, for example, you can easily access each item in a large array. Finding the
lowest value, or adding up all the values is much easier to implement using an array.
The following loop will sum up all the values in an array of 100 items:
for (int i = 0; i< 100; ++i)
sum += grades[i];
Remember to start with zero or you will miss the first item.
TIP: When specifying the size of an array, you can use a named constant or #defined
value, such as with the following:
#include<iostream>
const int MAX_SZ =50;
int main()
{
int grades[MAX_SZ];
}
OR
#include<iostream>
#define MAX_SZ 50;
int main()
{
int grades[MAX_SZ];
}
This is helpful for a couple of reasons. First, it improves program readability. It also makes
the program more versatile and maintainable because you can change any reference to
the size of the array in one easy to find location.
Initializing Arrays
If the initial values of an array are known, the elements in the array can be initialized when
declared, such as:
int counters[5] = { 0, 0, 0, 1, 5 };
The above line of code sets the value of counters [0] to 0, counters[1] to 0, counters[2] to
0, counters[3] to 1, and counters[4] to 5. This would be equivalent to the following 6 lines
of code:
int counters[5];
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 1;
counters[4] = 5;
It’s not necessary to completely initialize the entire array. If the first few are initialized, the
remaining are set to zero (0). Consider the following:
The first 3 elements are initialized to the values provided; the remaining 497 elements will
be set to zero (0). However, no assumptions may be made about the values of the
elements of an uninitialized array (i.e. they are NOT zero (0) by default).
If all the elements need to be initialized to something other than zero (0), the best way to
do that is to use a for loop.
int array_values[10];
int i;
for ( i = 0; i < 10; ++i )
array_values[i] = i * i;
This for loop initializes each element to the square of the element number (subscript
number), so the array will contain 0, 1, 4, 9, 16 25, 36, 47, 64, 81 after initialization.
C++ allows you to declare an array without specifying the number of elements only if you
initialize every element of the array when it is declared. The following:
int counters[] = { 0, 0, 0, 1, 5 };
You can also use the index numbers when initializing. So if you know specific elements
need to be initialized to a certain value, you can do the following:
Because the largest index number specified above is 99, sample_data will be set to
contain 100 elements; the remaining uninitialized elements initialized to zero (0).
Functions
Definition: A function is a reusable block of code that performs a specific task.
Example:
Pointers
Definition: A pointer is a variable that stores the memory address of another variable.
Example:
References
Definition: A reference is an alternate name for an existing variable.
Example:
Syntax
return_type function_name(parameter_list) {
// body of function
}
Example:
Function Types
User-defined functions: Written by the programmer.
Library functions: Provided by C++ libraries (e.g. sqrt() , abs() ).
Definition
Function Parameters
When calling a function in C++, values are passed to parameters. The way values are
passed determines whether the function can modify the original variable or just work on a
copy.
Call by Value
A copy of the actual value is passed.
Changes made inside the function do not affect the original variable.
Syntax:
void modify(int x) {
x = x + 5;
}
Example
int main() {
int a = 10;
modify(a);
cout << a; // Output: 10 (unchanged)
}
Note
Value copied
x y
a b
10 20
4Byte 4Byte 4Byte 20 20 4Byte
100 200
300 400
Address
Example
int main() {
int a = 10;
modify(&a);
cout << a; // Output: 15 (modified)
}
Note
Address copied
x y
a b
20 20
4Byte 4Byte 8Byte 100 200 8Byte
100 200
300 400
Address
Call by Reference
A reference (alias) of the original variable is passed.
Changes inside the function affect the original variable directly.
Syntax
Example
int main() {
int a = 10;
modify(a);
cout << a; // Output: 15 (modified)
}
Call by Reference
New local
reference are
x y created
a b
20 20
4Byte 4Byte
100 200
Address
Default Arguments
Allow parameters to have default values.
Call:
Const Arguments
Prevents function from modifying input.
Function Overloading
Function overloading means having more than one function with the same name in the
same scope, but each has different:
Number of parameters
Type of parameters
Order of parameters
Syntax
Important
The correct version is selected based on arguments passed during the function call
— this process is known as compile-time polymorphism.
Example
#include <iostream>
using namespace std;
int main() {
cout << add(3, 4) << endl; // Calls int version
cout << add(3.5f, 2.5f) << endl; // Calls float version
cout << add(1, 2, 3) << endl; // Calls 3-parameter version
}
Output:
7
6
6
Note
Invalid Example:
Recursion
What is Recursion?
Recursion is a programming technique where a function calls itself to solve a problem. It
breaks down a complex problem into smaller instances of the same problem.
void recursiveFunction() {
if (base_case_condition)
return; // base case
else
recursiveFunction(); // recursive call
}
Example: Factorial
int factorial(int n) {
if (n <= 1)
return 1; // base case
else
return n * factorial(n - 1); // recursive call
}
Example: Fibonacci
int fibonacci(int n) {
if (n <= 1)
return n;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
Common Issues
Class Declaration
A class in C++ is declared using the class keyword. It serves as a blueprint for creating
objects and defines the properties (data members) and behaviors (member functions).
Syntax:
class <ClassName> {
// Access Specifiers
// Data Members
// Member Functions
};
Object Creation
Objects are instances of a class. Each object gets its own copy of the class's data
members.
Syntax:
<ClassName> <ObjectName>;
Here, ClassName is the name of the class, and ObjectName is the name of the object.
Accessing Members
You can access class members using:
Data Members
objectName.dataMember;
Member Functions:
objectName.memberFunction();
Data Members:
pointerToObject->dataMember;
Member Functions:
pointerToObject->memberFunction();
Data Members
These are variables that store the attributes of a class. Each object of the class will have
its own copy of the data members.
Example
class Car {
string brand; // Data member
int speed; // Data member
};
Member Functions
Member functions define the behavior of the class. They operate on the data members of
the class.
Syntax:
class Car {
void start() {
cout << "Car started!" << endl;
}
};
class Car {
void start(); // Function prototype
};
void Car::start() {
cout << "Car started!" << endl;
}
Access Specifiers
Access specifiers control the visibility of class members. There are three types:
public : Members declared as public can be accessed from outside the class.
private : Members declared as private can only be accessed within the class. This
ensures encapsulation and data hiding. The members of a class in C++ are private
by default.
protected : Members declared as protected can be accessed in derived (inherited)
classes and the class itself.
Syntax
class Car {
private:
int speed; // Only accessible within the class
protected:
int fuel; // Accessible in the class and derived classes
public:
string brand; // Accessible from outside the class
};
public
Example :
#include <iostream>
using namespace std;
class Car {
public: // Public access specifier
string brand; // Public data member
void display() { // Public member function
cout << "Brand: " << brand << endl;
}
};
int main() {
Car car1;
car1.brand = "Toyota"; // Accessing public data member
car1.display(); // Accessing public member function
return 0;
}
Output
Brand: Toyota
private
Members declared as private are only accessible within the class. They cannot
be accessed directly from outside the class.
This is the default access specifier if no specifier is provided.
Private members are typically used to store sensitive or internal data, ensuring
encapsulation.
#include <iostream>
using namespace std;
class Car {
private: // Private access specifier
int speed; // Private data member
public:
void setSpeed(int s) { // Public member function to set speed
if (s > 0)
speed = s;
else
cout << "Invalid speed!" << endl;
}
int getSpeed() { // Public member function to get speed
return speed;
}
};
int main() {
Car car1;
// car1.speed = 100; // Error: 'speed' is private
car1.setSpeed(120); // Indirect access through public function
cout << "Speed: " << car1.getSpeed() << " km/h" << endl;
return 0;
}
protected
Members declared as protected are accessible within the class itself and in
derived classes.
They are not accessible directly from outside the class.
Protected members are used when designing inheritance hierarchies, where child
classes can access certain members of the parent class.
NB:
a typedef does not create a new type, it simply creates a synonym for an existing
type. The alias is treated by the compiler exactly as if you had written the original
type
`#include <iostream>
// Define a typedef alias "Integer" for the type int
typedef int Integer;
int main() {
Integer count = 5;
// 'count' is an int, via alias
std::cout << "count = " << count << std::endl;
return 0;
}
In this example, Integer is an alias for int . Declaring Integer count is exactly the
same as declaring int count . The compiler treats Integer as if it were int whenever
it sees it.
How ever incase of pointer or complex pointers we can used typrdef to make more
sense of datatype.
struct Node {
int data;
Node* next;
};
typedef struct Node* NodePtr; // NodePtr is an alias for "pointer to
Node"
Node n;
NodePtr head = &n; // head is a Node*
class Rectangle {
public:
int width, height;
int area() { return width * height; }
};
Object Creation
Memory Allocation
Constructor Called
Initialization
Object Usage
Methods Invoked
Destructor Called
Resource Cleanup
Memory Deallocated
Release Memory
Constructors
A constructor is a special member function in C++ that is automatically called when
an object of a class is created. It is primarily used to initialize the object's data
members and perform any setup required for the object.
1. Same Name as the Class: The constructor's name must match the name of the
class.
2. No Return Type: Constructors do not have a return type, not even void .
3. Automatically Called: It is invoked automatically when an object is created.
4. Can Be Overloaded: A class can have multiple constructors (constructor overloading)
with different parameter lists.
class ClassName {
public:
ClassName() {
// Initialization code
}
};
Types of Constructors
1. Default Constructor
A default constructor is a special type of constructor in C++ that takes no arguments or
has all default arguments. It is automatically invoked when an object of a class is
created without passing any arguments. Its primary purpose is to initialize an object
with default values.
Key Characteristics of a Default Constructor
Example
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() { // Default constructor
cout << "Default constructor called!" << endl;
}
};
int main() {
MyClass obj; // Default constructor is automatically called
return 0;
}
If you don’t define any constructor in your class, the compiler generates a default
constructor automatically.
class MyClass {
// Compiler provides an implicit default constructor
};
1. Automatic Initialization: It ensures that objects start with valid initial values,
preventing undefined behavior.
2. Ease of Use: Simplifies object creation when no specific initialization is required.
3. Supports Polymorphism: Plays a crucial role in initializing base and derived class
objects.
4. Compiler-Generated Simplicity: Eliminates the need for explicit initialization in
simple classes.
MyClass obj;
2. Parameterized Constructor
1. Takes Parameters:
Unlike a default constructor, a parameterized constructor accepts arguments to
initialize data members.
2. Called During Object Creation:
When an object is created with arguments, the parameterized constructor is
automatically invoked.
3. Constructor Overloading:
Parameterized constructors can be part of constructor overloading, where multiple
constructors exist with different parameter lists.
4. Initialization:
Typically used to initialize member variables with specific values or perform
complex initialization.
Example
#include <iostream>
using namespace std;
class MyClass {
int a, b;
public:
// Parameterized Constructor
MyClass(int x, int y) {
a = x;
b = y;
}
void display() {
cout << "a = " << a << ", b = " << b << endl;
}
};
int main() {
MyClass obj(10, 20); // Parameterized constructor is called
obj.display(); // Output: a = 10, b = 20
return 0;
}
1. Flexible Initialization:
Allows different objects of the same class to be initialized with different values.
2. Avoids Manual Initialization:
Simplifies initialization by encapsulating it within the constructor.
3. Enhances Code Readability:
Using parameterized constructors makes the code more concise and easier to
maintain.
Error Example
#include <iostream>
using namespace std;
class MyClass {
int a, b;
public:
// Parameterized Constructor
MyClass(int x, int y) {
a = x;
b = y;
}
void display() {
cout << "a = " << a << ", b = " << b << endl;
}
};
int main() {
MyClass obj(10, 20); // Parameterized constructor is called
MyClass obj_err; // Error
obj.display(); // Output: a = 10, b = 20
return 0;
}
As the user defined Parameterized constructor compiler will not add its default
constructor. Hence, user defined default constructor needs to be added also.
#include <iostream>
using namespace std;
class MyClass {
int a, b;
public:
// Default constructor
MyClass() {
a = 0;
b = 0;
}
// Parameterized Constructor
MyClass(int x, int y) {
a = x;
b = y;
}
void display() {
cout << "a = " << a << ", b = " << b << endl;
}
};
int main() {
MyClass obj(10, 20); // Parameterized constructor is called
MyClass obj_err; // Error
obj.display(); // Output: a = 10, b = 20
return 0;
}
If multiple constructors exist with similar parameter lists, ambiguities may arise.
Use distinct parameter types to avoid conflicts.
A constructor with default arguments is a constructor that allows you to provide default
values for some or all of its parameters. This means if an object is created without
providing certain arguments, the constructor will automatically use the default values.
Key Features
1. Default Values:
You specify default values in the constructor declaration.
If an argument is omitted when creating an object, the default value is used.
2. Combines Flexibility and Code Simplicity:
Instead of writing multiple overloaded constructors, you can use one constructor
with default arguments.
3. Order of Parameters:
Default arguments must be specified from right to left. Non-default arguments
should always precede default ones.
Syntax
class ClassName {
public:
ClassName(int a = 0, int b = 0); // Constructor with default
arguments
};
Example
#include <iostream>
using namespace std;
class MyClass {
int a, b;
public:
MyClass(int x = 0, int y = 0) { // Default arguments
a = x;
b = y;
cout << "Constructor called with a = " << a << " and b = " << b
<< endl;
}
};
int main() {
MyClass obj1; // Uses default values (a = 0, b = 0)
MyClass obj2(10); // Uses a = 10, b = 0
MyClass obj3(10, 20);// Uses a = 10, b = 20
return 0;
}
Destructor in C++
What is a Destructor?
A destructor is a special member function in C++ that is called automatically when an
object of the class goes out of scope or is explicitly deleted. Its primary purpose is to
release resources (like dynamic memory, file handles, etc.) allocated during the object's
lifetime.
Syntax
class ClassName {
public:
~ClassName() {
// Code for cleanup
}
};
Example
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass() {
cout << "Constructor called!" << endl;
}
~MyClass() {
cout << "Destructor called!" << endl;
}
};
int main() {
MyClass obj; // Constructor is called
cout << "Object in use..." << endl;
return 0; // Destructor is called when `obj` goes out of scope
}
Syntax:
Example:
Internal Behavior:
#include <iostream>
using namespace std;
enum Day {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
};
int main() {
Day today = Wednesday;
if (today == Wednesday) {
cout << "It's midweek!" << endl;
}
return 0;
}
Output :
It's midweek!
Enum values:
Sunday = 0
Monday = 1
Tuesday = 2
Wednesday = 3
Thursday = 4
Friday = 5
Saturday = 6
Notes
Syntax:
#include <iostream>
using namespace std;
int main() {
Color favorite = Color::Green;
return 0;
}
Output :
Data Initialization: Initialize data structures, instantiate classes, set variable values,
etc.
Build GUI: Place widgets (windows, dialog boxes, buttons, etc.) and define the events
they handle.
Callback Functions: Define and register callback functions with the operating system.
Make GUI Visible: Make the application windows visible and return control to the OS.
3. Event Handling
Parts of a GUI
GUI Programs vs Game Programs
Basic Game Loop
Continuous Processing: Unlike event loops, game loops process input continuously
and update the game state.
Start Game
Read Input
Process Input
Loop Back
Render Frame
Frames Per Second (FPS): The game loop cycles determine the game's FPS,
influencing smoothness.
Consistent Speed: Modern games must run at a consistent speed across different
hardware, unlike older games tied to specific hardware.
Game Library
SFML Library
SFML and Linux
SFML (Simple and Fast Multimedia Library) is a free, open-source, cross-platform
library designed for multimedia application development. It provides an easy-to-use
API for handling various multimedia components, making it a popular choice for game
development and other graphical applications.
Features of SFML
SFML is organized into several modules, each addressing specific aspects of
multimedia programming:
1. System Module:
Provides basic data types and utilities.
Handles time, threads, and other low-level functionalities.
2. Window Module:
Manages window creation, input handling, and OpenGL context settings.
Provides an abstraction for keyboard, mouse, and joystick input.
3. Graphics Module:
Offers 2D graphics rendering capabilities.
Supports sprites, shapes, text, and textures.
Includes basic transformations, such as scaling and rotation.
4. Audio Module:
Enables sound and music playback.
Supports audio streams and basic sound effects.
Works with formats like WAV, OGG, and FLAC.
5. Network Module:
Provides tools for network communication using TCP and UDP protocols.
Handles sockets, packet serialization, and more.
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
return 0;
}
Compilation Process :
./my-app
Output
Core Modules
The Core of SFML consists of five main modules:
Poll Events
Render Frame
Clear Screen
Draw Objects
while(1);
return 0;
}
1. sf::VideoMode Class
The sf::VideoMode class in SFML represents the video mode of a window, i.e., its
resolution (width & height) and bit depth (color depth in bits per pixel - BPP).
class sf::VideoMode
Common Constructors:
sf::VideoMode();
sf::VideoMode(unsigned int width, unsigned int height,
unsigned int bitsPerPixel = 32);
Example:
// Create a 1920x1080 video mode with a default bit depth (32 BPP)
sf::VideoMode vm(1920, 1080);
Important Methods:
sf::VideoMode::getDesktopMode();
sf::VideoMode::getFullscreenModes();
2. sf::RenderWindow Class
The sf::RenderWindow class is a window that can render graphics. It extends
sf::Window and adds rendering functionalities.
#include <SFML/Graphics.hpp>
int main()
{
VideoMode vm(1920, 1080); // Create a video mode object
while (window.isOpen())
{
if (Keyboard::isKeyPressed(Keyboard::Escape)) // Handel player
input
{
window.close();
}
/*
Update the scene
*/
/*
Draw the scene
*/
Create VideoMode
Create Window
RenderWindow
window(vm, 'Timber!!!',
Style::Fullscreen)
Check Escape Ke
if
(Keyboard::isKeyPressed(Keyboard::Escap
Yes No
Update Scene
window.clear()
Render game scene
Display frame
window.display()
Sprites in a game
A sprite is a 2D image or animation used in a game to represent characters, objects, or
effects. It is a key element in 2D game development and is typically rendered on the
screen as a graphical object.
Types of Sprites:
1. Static Sprites – A single image that does not change (e.g., a tree or rock).
2. Animated Sprites – A sequence of images (frames) that create an animation (e.g.,
walking, jumping).
3. Sprite Sheets – A collection of images arranged in a grid to optimize animation and
performance.
4. Tiled Sprites – Small repeating textures used to create large environments like floors
and walls.
Rendering: Sprites are drawn by the game engine onto the screen.
Collision Detection: They interact with other objects based on bounding boxes or
pixel detection.
Transformation: They can be moved, rotated, scaled, or flipped based on game logic.
Animation: Frame-by-frame changes give the illusion of movement (e.g., walking
cycle).
2D Games: Platformers, RPGs, puzzle games (e.g., Super Mario Bros., Celeste).
UI Elements: Buttons, icons, menus in both 2D and 3D games.
Special Effects: Fire, smoke, explosions, magic spells.
Types of sprites
1. Character Sprites
2. Environment Sprites
Background Sprites – Static or layered images that create the backdrop of the game
(e.g., sky, mountains, buildings).
Foreground Sprites – Elements that appear in front of characters, such as trees,
fences, or rocks.
Platforms and Terrain – Ground, bridges, floating platforms, and surfaces that
characters interact with.
Collectibles – Coins, gems, power-ups, or keys that the player can collect.
Weapons & Tools – Guns, swords, shields, or tools used by the player or NPCs.
Doors & Switches – Objects that trigger events when interacted with.
Health & Mana Bars – Displays the status of the player’s health and resources.
Icons & Buttons – Inventory icons, ability icons, or in-game buttons.
Text and Dialog Boxes – UI elements that display conversations or information.
6. Parallax Sprites
Rendering Process
Game Window Setup – Initializes resolution, aspect ratio, and rendering context.
Loading Sprites – Stores textures in GPU memory for efficient access.
Drawing Scene – Clears the screen and draws objects in layers (background, sprites,
UI).
Frame Buffer & VSync – Ensures smooth rendering by managing refresh rates.
Sprite Interaction
Movement & Physics – Sprites respond to user input, velocity, and gravity.
Collision Detection – Detects interactions using bounding boxes, circles, or pixel-
perfect methods.
Handling Collisions – Adjusts positions, triggers effects, and executes game logic.
Game Description:
Gameplay: The player controls a lumberjack who stands beside a tall tree. They must
chop from either the left or right side while avoiding oncoming branches. The game is
fast-paced, requiring quick reflexes and decision-making.
Controls: Typically, the player taps or presses keys to chop the tree on either side.
Mechanics:
The tree falls continuously as the player chops.
Each chop scores points and slightly refills the timer.
Hitting a branch results in an instant game over.
The longer the player chops, the faster the tree falls, increasing difficulty.
Some versions introduce power-ups or new characters with special abilities.
Visual Design:
Simple, pixel-art or cartoonish aesthetic.
Background changes with progression.
Characters can be customizable or unlockable.
Smooth animation for chopping, tree falling, and branch movement.
int main()
{
VideoMode vm(1920,1080);
// Create a sprit
Sprite spriteBackground;
while(window.isOpen())
{
if (Keyboard::isKeyPressed(Keyboard::Escape)) // Handel player
input
{
window.close();
}
window.clear();
window.display();
}
}
sf::RenderWindow Class
Purpose:
sf::Texture Class
Purpose:
Usage in Code:
Texture textureBackground;
textureBackground.loadFromFile("background.png");
Loads the image "background.png" into the textureBackground object.
sf::Sprite Class
Purpose:
For example:
(0, 0) is the origin — usually the top-left or bottom-left corner depending on the
engine.
(100, 200) means:
100 units right
200 units down or up, depending on the coordinate system
Visual Example:
y ▲
│
└────────▶ x
(0, 0)
int main()
{
VideoMode vm(1920,1080);
Texture textureCloud;
textureCloud.loadFromFile("cloud.png");
Sprite spriteCloud;
spriteCloud.setTexture(textureCloud);
spriteCloud.setPosition(0, 200);
while(window.isOpen())
{
if (Keyboard::isKeyPressed(Keyboard::Escape)) // Handel player
input
{
window.close();
}
window.clear();
window.display();
}
}
NB: You will see the a cloud moving from left to right. We achieve that by changing
the x coordinate of cloud sprite in each frame.
But we don't want the cloud to move out of the window. So as soon as the cloud reaches
the right border we want the cloud to restart from left again.
int main()
{
VideoMode vm(1920,1080);
Texture textureCloud;
textureCloud.loadFromFile("cloud.png");
Sprite spriteCloud;
spriteCloud.setTexture(textureCloud);
spriteCloud.setPosition(0, 200);
while(window.isOpen())
{
if (Keyboard::isKeyPressed(Keyboard::Escape)) // Handel player
input
{
window.close();
}
window.clear();
window.display();
}
}
Note
The movement depends on the frame which is highly unreliable for real time use
as frame rendering may not happen with equal time interval.
Hence, we may want to add the movement to the time elapsed to make sure
movement of the sprite according to time interval.
#include<SFML/Graphics.hpp>
using namespace sf;
int main()
{
VideoMode vm(1920,1080);
Texture textureCloud;
textureCloud.loadFromFile("cloud.png");
Sprite spriteCloud;
spriteCloud.setTexture(textureCloud);
spriteCloud.setPosition(0, 200);
float cloudSpeed = 15; // With how much time it should cover the
window width
float cloudSpeedPerSec = 1920/cloudSpeed;
while(window.isOpen())
{
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
window.close();
}
dt = ct.restart();
window.clear();
window.display();
}
}
What is a HUD?
HUD (Heads-Up Display) refers to on-screen elements that show information like:
Score
Health bars
Ammo count
Timer
Minimap
Example
#include <SFML/Graphics.hpp>
#include <string>
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "Timber !!!");
// Load font
sf::Font font;
font.loadFromFile("KOMIKAP_.ttf");
// Main loop
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
// Update score
score += 1;
scoreText.setString("Score: " + std::to_string(score));
// Render
window.clear();
window.draw(scoreText);
window.display();
}
return 0;
}
Time-Bar HUD
Objective
Display a time bar (like a health/progress bar) at the bottom of the screen.
The bar shrinks over a fixed duration (e.g., 10 seconds).
After time runs out, the bar is gone (empty).
#include <SFML/Graphics.hpp>
using namespace sf;
int main() {
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Time Bar");
while (window.isOpen()) {
dt = ct.restart();
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
// Update elapsed time
elapsedTime += dt.asSeconds();
// Calculate the remaining ratio and update the time bar width
float remainingRatio = ((totalTime - elapsedTime) / totalTime);
if(remainingRatio > 0.0f)
timeBar.setSize(sf::Vector2f(barWidth * remainingRatio,
barHeight));
else
timeBar.setSize(sf::Vector2f(0, barHeight));
// Render everything
window.clear();
window.draw(timeBar);
window.display();
}
return 0;
}
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <sstream>
#include <cmath>
using namespace sf;
// Updates cloud movement from left to right and resets when off screen
void cloudUpdate(Sprite &spriteCloud, Time &dt, float
&cloudPixelPerSecond) {
float x = spriteCloud.getPosition().x;
float y = spriteCloud.getPosition().y;
if (x > 1980) {
spriteCloud.setPosition(-200, y); // reset cloud to left
} else {
spriteCloud.setPosition(x + (dt.asSeconds() *
cloudPixelPerSecond), y); // move right
}
}
// Updates bee movement with sine wave and resets position after off-
screen
void beeUpdate(Sprite &spriteBee, Time &dt, float &beePixelPerSecond) {
static float timex = 0;
static float y_dir = 820;
timex += dt.asSeconds();
float x = spriteBee.getPosition().x;
float y = spriteBee.getPosition().y;
if (x < 0) {
y_dir = 820 + rand() % 200 - 100; // randomize vertical position
spriteBee.setPosition(2000, y); // reset to right
} else {
y = y_dir + 50 * sin(timex); // vertical sine motion
spriteBee.setPosition(x - (dt.asSeconds() * beePixelPerSecond),
y); // move left
}
}
int main() {
VideoMode vm(800, 600);
RenderWindow window(vm, "Timber Man ");
// Bee setup
Sprite spriteBee;
Texture textureBee;
textureBee.loadFromFile("bee.png");
spriteBee.setTexture(textureBee);
spriteBee.setPosition(1980, 820);
float beePixelPerSecond = 1980 / 15.0f;
// Tree
Sprite spriteTree;
Texture textureTree;
textureTree.loadFromFile("tree.png");
spriteTree.setTexture(textureTree);
spriteTree.setPosition(810, 0);
// Score display
int score_val = 0;
Text scoreText;
Font font;
font.loadFromFile("KOMIKAP_.ttf");
scoreText.setFont(font);
scoreText.setString("Score = 0");
scoreText.setPosition(20, 20);
scoreText.setCharacterSize(100);
scoreText.setFillColor(Color::Yellow);
// Branches
int numBranches = 6;
Sprite spriteBranch[numBranches];
Texture textureBranch;
textureBranch.loadFromFile("branch.png");
for (int i = 0; i < numBranches; i++) {
spriteBranch[i].setTexture(textureBranch);
spriteBranch[i].setPosition(590, -200);
spriteBranch[i].setOrigin(220, 40);
spriteBranch[i].setRotation(180);
}
// Player setup
Sprite spritePlayer;
Texture texturePlayer;
texturePlayer.loadFromFile("player.png");
spritePlayer.setTexture(texturePlayer);
spritePlayer.setPosition(1130, 708);
// Log setup
Sprite spriteLog;
Texture textureLog;
textureLog.loadFromFile("log.png");
spriteLog.setTexture(textureLog);
spriteLog.setPosition(810, 780);
float speedLog = 0.3;
float logPixelPexSecX = 990 / speedLog;
float logPixelPerSecY = 200 / speedLog;
int logDir = 0;
// Axe
Sprite spriteAxe;
Texture textureAxe;
textureAxe.loadFromFile("axe.png");
spriteAxe.setTexture(textureAxe);
spriteAxe.setPosition(2300, 800);
// Sound effect
Sound chop;
SoundBuffer chopSound;
chopSound.loadFromFile("chop.wav");
chop.setBuffer(chopSound);
Event ev;
while (window.pollEvent(ev)) {
if (ev.type == Event::Closed) window.close();
if (ev.type == Event::KeyReleased && !acceptInput) {
spriteAxe.setPosition(2300, 800);
acceptInput = true;
}
}
spritePlayer.setPosition(1130, 708);
spriteRip.setPosition(2300, 750);
spriteLog.setPosition(810, 780);
logActive = false;
spritePlayer.setScale(1, 1);
} else {
gamestart = true;
pause = false;
messageText.setString("");
}
acceptInput = false;
}
// Chop left
if (Keyboard::isKeyPressed(Keyboard::Left) && !pause) {
score_val++;
timeRemaining += (2.0f / score_val) + 0.2f;
branchUpdate(numBranches, spriteBranch, chopHeight);
spritePlayer.setPosition(790, 708);
spriteAxe.setPosition(740, 800);
spritePlayer.setScale(-1, 1);
logActive = true;
logDir = 1;
chop.play();
acceptInput = false;
}
// Chop right
if (Keyboard::isKeyPressed(Keyboard::Right) && !pause) {
score_val++;
timeRemaining += (2.0f / score_val) + 0.2f;
branchUpdate(numBranches, spriteBranch, chopHeight);
spritePlayer.setPosition(1130, 708);
spritePlayer.setScale(1, 1);
spriteAxe.setPosition(1040, 800);
logActive = true;
logDir = -1;
chop.play();
acceptInput = false;
}
}
//////////////////////////////////////////////////
// RENDER SECTION
window.draw(spritePlayer);
window.draw(spriteLog);
window.draw(spriteAxe);
window.draw(spriteRip);
window.draw(spriteBee);
window.draw(scoreText);
window.draw(messageText);
window.draw(timebar);
return 0;
}
Pong Game without Class
Game Objectives
1. Prevent the Ball from Falling
Control the bat/paddle at the bottom using the Left and Right arrow keys.
Ensure the ball bounces back by hitting it with the bat.
If the ball hits the bottom wall (misses the bat), the player loses one life.
2. Score Points
When the ball hits the top wall, the player earns 1 point.
The objective is to score as many points as possible before losing all lives.
4. Game Controls
Action Key
Move Bat Left Left Arrow
Move Bat Right Right Arrow
Restart After Game Over Enter
Quit Game Escape or Close window
Score to 0
Lives to 3
Ball starts from the top with random X direction.
Game Code
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
using namespace sf;
using namespace std;
int main()
{
VideoMode video(800, 600);
RenderWindow window(video, "Pong Game");
window.setView(view);
RectangleShape batShape;
float batWidth = 200;
float batHeight = 10;
float batSpeed = 2;
float batPixSec = windowHeight / batSpeed;
batShape.setOrigin(batWidth / 2, batHeight / 2);
batShape.setSize(Vector2f(batWidth, batHeight));
batShape.setFillColor(Color::White);
batShape.setPosition(windowWidth / 2, windowHeight - 20);
CircleShape ballShape;
float radius = 20;
float ballSpeed = 3;
float ballPixSecX = windowWidth / ballSpeed;
float ballPixSecY = windowHeight / ballSpeed;
ballShape.setRadius(radius);
ballShape.setFillColor(Color::Magenta);
ballShape.setPosition(20 + rand()%(int)(windowWidth-20) , 20);
Font font;
font.loadFromFile("KOMIKAP_.ttf");
Text scoreText;
scoreText.setFont(font);
scoreText.setCharacterSize(75);
scoreText.setFillColor(Color::White);
scoreText.setPosition(20, 20);
Text liveText;
liveText.setFont(font);
liveText.setCharacterSize(75);
liveText.setFillColor(Color::White);
float scoreVal = 0;
float liveVal = 3;
int ballMoveX = rand()%2 == 0 ? -1 : 1;
int ballMoveY = 1;
Clock ct;
Time dt;
while (window.isOpen())
{
dt = ct.restart();
Event ev;
while (window.pollEvent(ev))
{
if (ev.type == Event::Closed || (ev.type == Event::KeyPressed
&& ev.key.code == Keyboard::Escape))
window.close();
if (ev.type == Event::KeyPressed && ev.key.code ==
Keyboard::Enter && gameOver)
{
paused = false;
gameOver = false;
bounceTop = false;
bounceBottom = true;
scoreVal = 0;
liveVal = 3;
ballShape.setPosition(windowWidth / 2, 20);
ballMoveX = rand()%2 == 0 ? -1 : 1;
ballMoveY = 1;
}
}
if(!gameOver)
ss1 << "Lives : " << liveVal;
else
ss1 << "Game Over .. Press Enter to restart";
liveText.setString(ss1.str());
if (!paused)
{
if (Keyboard::isKeyPressed(Keyboard::Left))
{
float x = batShape.getPosition().x;
float y = batShape.getPosition().y;
x = x - dt.asSeconds() * batPixSec;
if (x < batWidth / 2)
x = batWidth / 2;
batShape.setPosition(x, y);
}
if (Keyboard::isKeyPressed(Keyboard::Right))
{
float x = batShape.getPosition().x;
float y = batShape.getPosition().y;
x = x + dt.asSeconds() * batPixSec;
if (x > windowWidth - batWidth / 2)
x = windowWidth - batWidth / 2;
batShape.setPosition(x, y);
}
float x = ballShape.getPosition().x;
float y = ballShape.getPosition().y;
x = x + dt.asSeconds() * ballPixSecX * ballMoveX;
y = y + dt.asSeconds() * ballPixSecY * ballMoveY;
if (x > windowWidth - radius)
ballMoveX = -1;
if (x < radius)
ballMoveX = 1;
if ((y > windowHeight - radius ||
batShape.getGlobalBounds().intersects(ballShape.getGlobalBounds())) &&
bounceBottom)
{
if (y > windowHeight - radius)
{
liveVal = liveVal - 1;
}
ballMoveY = -1;
bounceTop = true;
bounceBottom = false;
}
if (y < radius && bounceTop)
{
ballMoveY = 1;
scoreVal = scoreVal + 1;
bounceTop = false;
bounceBottom = true;
}
ballShape.setPosition(x, y);
}
if(liveVal == 0)
{
paused = true;
gameOver = true;
ballShape.setPosition(windowWidth/2, windowHeight/2);
}
window.clear();
window.draw(batShape);
window.draw(ballShape);
window.draw(scoreText);
window.draw(liveText);
window.display();
}
}
Pong Game with Class
Ball.h File
#pragma once
#include<SFML/Graphics.hpp>
using namespace sf;
class Ball{
private:
CircleShape ballShape;
float pos_x, pos_y;
float ballSpeed;
float ballPixelPerSecX ;
float ballPixelPerSecy;
int moveX;//1: Right -1: left;
int moveY;//1:Down -1:Up
public:
Ball();
CircleShape returnShape();
void upadteBall(Time &dt);
void ballBounceRight();
void ballBounceLeft();
void ballBounceTop(int &score, bool &incScore);
void ballBounceBottom(bool &incScore, int &live);
void ballTochesBat(FloatRect batBound, bool &incScore);
};
Ball.cpp File
#include "ball.h"
Ball::Ball()
{
ballShape.setFillColor(Color::White);
ballShape.setRadius(40);
pos_x = 60 + rand()%1870;
pos_y = 60;
ballShape.setPosition(pos_x,pos_y);
moveY= 1;
moveX = 1;
ballSpeed = 5;
ballPixelPerSecX = 1980/ballSpeed;
ballPixelPerSecy = 1020/ballSpeed;
}
CircleShape Ball::returnShape()
{
return(ballShape);
}
#pragma once
#include<SFML/Graphics.hpp>
using namespace sf;
class Bat{
private:
RectangleShape batShape;
float batSpeed;
float batPixelPerSec;
public:
Bat();
void moveLeft(Time &dt);
void moveRight(Time &dt);
RectangleShape returnShape();
};
Bat.cpp File
#include "bat.h"
Bat::Bat()
{
batShape.setFillColor(Color::White);
batShape.setSize(Vector2f(400, 10));
batShape.setPosition(1980 / 2.0f - 200, 1020 - 40);
batSpeed = 5;
batPixelPerSec = 1980 / batSpeed;
}
RectangleShape Bat::returnShape()
{
return(batShape);
}
PongGame.cpp File
#include <SFML/Graphics.hpp>
#include <sstream>
#include "bat.h"
#include "bat.cpp"
#include "ball.h"
#include "ball.cpp"
int main()
{
VideoMode vm(800, 600);
RenderWindow window(vm, "Pong Game!!!");
int lives = 3;
int score = 0;
livesText.setFont(ft);
livesText.setCharacterSize(75);
livesText.setFillColor(Color::White);
livesText.setString("Lives = 3");
Bat bat;
Ball ball;
Clock ct;
Time dt;
while (window.isOpen())
{
dt = ct.restart();
// game Logic
Event ev;
while (window.pollEvent(ev))
{
if (ev.type == Event::KeyReleased && !acceptInput)
{
acceptInput = true;
}
if (ev.type == Event::Closed)
{
window.close();
}
}
if (acceptInput)
{
if (Keyboard::isKeyPressed(Keyboard::Space))
{
paused = !paused;
acceptInput = false;
}
if (Keyboard::isKeyPressed(Keyboard::Enter))
{
gameOver = false;
paused = false;
// re-init
lives = 3;
score = 0;
acceptInput = false;
incScore = false;
ball = Ball();
}
}
if (!paused)
{
if (lives == 0)
{
gameOver = true;
paused = true;
}
if (Keyboard::isKeyPressed(Keyboard::Left))
{
bat.moveLeft(dt);
}
if (Keyboard::isKeyPressed(Keyboard::Right))
{
bat.moveRight(dt);
}
stringstream str_score, str_lives;
str_score << "Score = " << score;
str_lives << "Lives = " << lives;
scoreText.setString(str_score.str());
livesText.setString(str_lives.str());
ball.upadteBall(dt);
ball.ballBounceRight();
ball.ballBounceLeft();
ball.ballBounceTop(score, incScore);
ball.ballBounceBottom(incScore, lives);
ball.ballTochesBat(bat.returnShape().getGlobalBounds(),
incScore);
}
window.clear();
// draw the sprites
window.draw(bat.returnShape());
window.draw(ball.returnShape());
window.draw(scoreText);
window.draw(livesText);
window.display();
}
}
Zombie Arena Game
Primary Objectives
Learn to draws frames according to user input. (Previously all frame sprites are
drawn irrespective of user input.)
Exploring the SFML View class.
#include<SFML/Graphics.hpp>
#include<iostream>
#include<cmath>
using namespace sf;
using namespace std;
int main()
{
VideoMode video(800, 600);
RenderWindow window(video, "Zombie Arena !!!");
Sprite spritePlayer;
Texture texturePlayer;
texturePlayer.loadFromFile("player.png");
spritePlayer.setTexture(texturePlayer);
FloatRect playerBound = spritePlayer.getLocalBounds();
spritePlayer.setOrigin(playerBound.width/2, playerBound.height/2);
float playerSpeed = 5;
float pixelPerSecPlayerX = window.getSize().x/ playerSpeed;
float pixelPerSecPlayerY = window.getSize().y/ playerSpeed;
Clock ct;
Time dt;
spritePlayer.setPosition(window.getSize().x/2, window.getSize().y/2);
while(window.isOpen())
{
dt = ct.restart();
Event ev;
while(window.pollEvent(ev))
{
if(ev.type == Event::Closed)
{
window.close();
}
}
float x = spritePlayer.getPosition().x;
float y = spritePlayer.getPosition().y;
if(Keyboard::isKeyPressed(Keyboard::A))
x = x - dt.asSeconds() * pixelPerSecPlayerX;
if(Keyboard::isKeyPressed(Keyboard::D))
x = x + dt.asSeconds() * pixelPerSecPlayerX;
if(Keyboard::isKeyPressed(Keyboard::W))
y = y - dt.asSeconds() * pixelPerSecPlayerY;
if(Keyboard::isKeyPressed(Keyboard::S))
y = y + dt.asSeconds() * pixelPerSecPlayerY;
spritePlayer.setPosition(x,y);
Vector2i mousePos = Mouse::getPosition(window);
Vector2f mouseWindowPos = window.mapPixelToCoords(mousePos);
float dx = mouseWindowPos.x - x;
float dy =mouseWindowPos.y - y;
float angle = atan2(dy, dx) * (180.0/3.141159f);
spritePlayer.setRotation(angle);
window.clear(Color::White);
window.draw(spritePlayer);
window.display();
}
return(0);
}
Game Screens
In zombie area games there are 4 states:
PAUSED
LEVELING_UP
GAME_OVER
PLAYING
Following Figure Shows all the required Screen based on state of the game
Landing Screen
GAME_OVER
Option Screen
Pause Screen
LEVELING_UP PLAYING
or
GAME_OVER
PLAYING PAUSED
Game Screen
#include <SFML/Graphics.hpp>
#include <sstream>
#include <iostream>
#include <cmath>
using namespace sf;
using namespace std;
int main()
{
Sprite spriteBackground;
Texture textureBackground;
textureBackground.loadFromFile("background.png");
spriteBackground.setTexture(textureBackground);
Font font;
font.loadFromFile("zombiecontrol.ttf");
Text textMessage;
textMessage.setFont(font);
textMessage.setFillColor(Color::White);
textMessage.setCharacterSize(50);
int score = 0;
Text textScore;
textScore.setFont(font);
textScore.setFillColor(Color::White);
textScore.setCharacterSize(40);
textScore.setPosition(20, 20);
textScore.setString("Score : 000");
int hiScore = 0;
Text textHiScore;
textHiScore.setFont(font);
textHiScore.setFillColor(Color::White);
textHiScore.setCharacterSize(40);
textHiScore.setString("Hi Score : 000");
textHiScore.setPosition(gameResolution.x -
textHiScore.getLocalBounds().width - 20, 20);
}
if (ev.type == Event::KeyPressed && ev.key.code ==
Keyboard::Space)
{
if (state == State::PLAYING)
{
state = State::PAUSED;
}
else if (state == State::PAUSED)
{
state = State::PLAYING;
}
}
if (ev.type == Event::KeyPressed && ev.key.code ==
Keyboard::R)
{
state = State::GAME_OVER;
}
}
textMessage.setString("");
stringstream scoreStream;
scoreStream << "Score : " << score;
textScore.setString(scoreStream.str());
stringstream hiScoreStream;
hiScoreStream << "Hi Score : " << hiScore;
textHiScore.setString(hiScoreStream.str());
textHiScore.setPosition(gameResolution.x -
textHiScore.getLocalBounds().width - 20, 20);
}
if (state == State::LEVELING_UP)
{
std::stringstream levelUpStream;
levelUpStream << "1- Increased rate of fire"
<< "\n2- Increased clip size(next reload)"
<< "\n3- Increased max health"
<< "\n4- Increased run speed"
<< "\n5- More and better health pickups"
<< "\n6- More and better ammo pickups";
textMessage.setString(levelUpStream.str());
textMessage.setPosition(gameResolution.x / 2 -
textMessage.getLocalBounds().width / 2,
gameResolution.y / 2 -
textMessage.getLocalBounds().height / 2);
}
if (state == State::GAME_OVER)
{
textMessage.setString("Press Enter to Start the Game !!");
textMessage.setPosition(gameResolution.x / 2 -
textMessage.getLocalBounds().width / 2,
gameResolution.y / 2 -
textMessage.getLocalBounds().height / 2);
}
window.setView(hudView);
window.draw(textScore);
window.draw(textHiScore);
}
if (state == State::LEVELING_UP)
{
window.draw(spriteBackground);
window.draw(textMessage);
}
if (state == State::GAME_OVER)
{
window.draw(spriteBackground);
window.draw(textMessage);
}
window.display();
}
return (0);
}
Working with Sprite Sheet for Designing Arena
Objective
Type Description
sf::Points Just dots
sf::Lines Unconnected lines (2 points each)
sf::LineStrip Connected line path
sf::Triangles Individual triangles (3 pts)
sf::TriangleStrip Connected triangle mesh
sf::TriangleFan Fan-like structure (circle)
sf::Quads 4-point rectangles
int main()
{
RenderWindow window(VideoMode(800, 600), "SFML Window tile example");
Texture texture;
texture.loadFromFile("background_sheet.png");
while (window.isOpen())
{
Event event;
while (window.pollEvent(event)) {
if (event.type == Event::Closed) {
window.close();
}
}
window.clear();
RenderStates states;
states.texture = &texture;
window.draw(vt, states);
window.display();
}
}
Output:
Requirements
For 1 tile 4 Quad data types are needed. (as seen in previous example)
Hence, for 10x10 tiles we need 400 Quads.
Vertex array will be used to create the 400 Quads.
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(800, 600), "SFML Window tile example");
Texture texture;
texture.loadFromFile("background_sheet.png");
int rowTiles = 10;
int columnTiles = 10;
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
{
window.close();
}
}
window.clear();
RenderStates states;
states.texture = &texture;
window.draw(vt, states);
window.display();
}
}
Output:
Placing random tile (stone, grass or mud) texture to entire
10x10 arena.
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(800, 600), "SFML Window tile example");
Texture texture;
texture.loadFromFile("background_sheet.png");
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
{
window.close();
}
}
window.clear();
RenderStates states;
states.texture = &texture;
window.draw(vt, states);
window.display();
}
}
Output
#include <SFML/Graphics.hpp>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(800, 600), "SFML Window tile example");
Texture texture;
texture.loadFromFile("background_sheet.png");
while (window.isOpen())
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
{
window.close();
}
}
window.clear();
RenderStates states;
states.texture = &texture;
window.draw(vt, states);
window.display();
}
}
Output:
Working with View
sf::View class plays a critical role in controlling what part of the 2D world is
visible on the screen. It acts like a camera or window into the game world.
Importance of sf::View in SFML
1. Defines What to Show
Controls which section of your world is displayed in the render window.
Useful for large worlds or maps where only a portion should be visible.
2. Enables Camera Movement
You can move the view (pan), zoom in/out, or rotate it to simulate a dynamic
camera.
Great for player following, cutscenes, or map exploration.
3. Decouples Game World from Screen Size
You can design your game world in world coordinates (e.g., 1000x1000) and
still show only a portion that fits in the screen.
This makes it easier to handle different screen resolutions or window sizes.
4. Allows UI Separation
You can set a fixed view for UI elements (like health bars or menus) that
doesn't move with the game world.
Helps in organizing layers (game world vs. HUD).
5. Supports Zooming and Scaling
view.zoom() lets you zoom into or out of the scene dynamically.
Useful for strategy games or maps.
800
600
Game World
800
1980
1020
Game World
#include <SFML/Graphics.hpp>
#include <cmath>
using namespace sf;
int main()
{
RenderWindow window(VideoMode(1980, 1020), "SFML Window tile
example");
Texture texture;
texture.loadFromFile("background_sheet.png");
Sprite spritePlayer;
Texture texturePlayer;
texturePlayer.loadFromFile("player.png");
spritePlayer.setTexture(texturePlayer);
FloatRect playerBound = spritePlayer.getLocalBounds();
spritePlayer.setOrigin(playerBound.width/2, playerBound.height/2);
float playerSpeed = 5;
float pixelPerSecPlayerX = window.getSize().x/ playerSpeed;
float pixelPerSecPlayerY = window.getSize().y/ playerSpeed;
Clock ct;
Time dt;
spritePlayer.setPosition(arenaWidth/2, arenaHeight/2);
while (window.isOpen())
{
dt = ct.restart();
Event ev;
while(window.pollEvent(ev))
{
if(ev.type == Event::Closed)
{
window.close();
}
}
float x = spritePlayer.getPosition().x;
float y = spritePlayer.getPosition().y;
if(Keyboard::isKeyPressed(Keyboard::A))
x = x - dt.asSeconds() * pixelPerSecPlayerX;
if(Keyboard::isKeyPressed(Keyboard::D))
x = x + dt.asSeconds() * pixelPerSecPlayerX;
if(Keyboard::isKeyPressed(Keyboard::W))
y = y - dt.asSeconds() * pixelPerSecPlayerY;
if(Keyboard::isKeyPressed(Keyboard::S))
y = y + dt.asSeconds() * pixelPerSecPlayerY;
if(x > 500)
x = 500;
if(y > 500)
y = 500;
if(x < 0)
x = 0;
if(y < 0)
y = 0;
spritePlayer.setPosition(x,y);
window.clear();
RenderStates states;
states.texture = &texture;
window.draw(vt, states);
window.draw(spritePlayer);
window.display();
}
}
(0,0)
(250,250)
View Center
Sometime the game world can be bigger than the visible frame. In such a case, we
want to move the arena with the player movement. We must set the center of the view
to be the player center.
view.setCenter(spritePlayer.getPosition());
window.setView(view);
The HUD is drawn in same view HUD will also move with the player movement. For
example :
We can see the Score: 000 HUD moved with the player. We want to set score HUD to
be fixed at the top. Hence, we need tow separate views
1. The player View which will move with the player.
2. The HUD view which will remain fixed to display the HUD at a fixed position
#include <SFML/Graphics.hpp>
#include <cmath>
using namespace sf;
int main() {
RenderWindow window(VideoMode(800, 600), "SFML Window tile example");
Texture texture;
texture.loadFromFile("background_sheet.png");
Sprite spritePlayer;
Texture texturePlayer;
texturePlayer.loadFromFile("player.png");
spritePlayer.setTexture(texturePlayer);
FloatRect playerBound = spritePlayer.getLocalBounds();
spritePlayer.setOrigin(playerBound.width / 2, playerBound.height / 2);
float playerSpeed = 5;
float pixelPerSecPlayerX = window.getSize().x / playerSpeed;
float pixelPerSecPlayerY = window.getSize().y / playerSpeed;
Clock ct;
Time dt;
spritePlayer.setPosition(arenaSize.x / 2, arenaSize.y / 2);
while (window.isOpen()) {
dt = ct.restart();
Event ev;
while (window.pollEvent(ev)) {
if (ev.type == Event::Closed) {
window.close();
}
}
float x = spritePlayer.getPosition().x;
float y = spritePlayer.getPosition().y;
if (Keyboard::isKeyPressed(Keyboard::A))
x = x - dt.asSeconds() * pixelPerSecPlayerX;
if (Keyboard::isKeyPressed(Keyboard::D))
x = x + dt.asSeconds() * pixelPerSecPlayerX;
if (Keyboard::isKeyPressed(Keyboard::W))
y = y - dt.asSeconds() * pixelPerSecPlayerY;
if (Keyboard::isKeyPressed(Keyboard::S))
y = y + dt.asSeconds() * pixelPerSecPlayerY;
if (x > arenaSize.x - 50)
x = arenaSize.x - 50;
if (y > arenaSize.y - 50)
y = arenaSize.y - 50;
if (x < 50)
x = 50;
if (y < 50)
y = 50;
spritePlayer.setPosition(x, y);
view.setCenter(spritePlayer.getPosition());
window.setView(view);
float dx = mouseWindowPos.x - x;
float dy = mouseWindowPos.y - y;
window.clear();
RenderStates states;
states.texture = &texture;
window.draw(vt, states);
window.draw(spritePlayer);
//Player Class
#pragma once
#include <cmath>
#include <SFML/Graphics.hpp>
using namespace sf;
class Player
{
private:
const float START_SPEED = 200;
const float START_HEALTH = 100;
// And a texture
// !!Watch this space!!
Texture m_Texture;
void moveRight();
void moveUp();
void moveDown();
void stopRight();
void stopUp();
void stopDown();
Player::Player()
{
m_Speed = START_SPEED;
m_Health = START_HEALTH;
m_MaxHealth = START_HEALTH;
Time Player::getLastHitTime()
{
return m_LastHit;
}
FloatRect Player::getPosition()
{
return m_Sprite.getGlobalBounds();
}
Vector2f Player::getCenter()
{
return m_Position;
}
float Player::getRotation()
{
return m_Sprite.getRotation();
}
Sprite Player::getSprite()
{
return m_Sprite;
}
int Player::getHealth()
{
return m_Health;
}
void Player::moveLeft()
{
m_LeftPressed = true;
}
void Player::moveRight()
{
m_RightPressed = true;
}
void Player::moveUp()
{
m_UpPressed = true;
}
void Player::moveDown()
{
m_DownPressed = true;
}
void Player::stopLeft()
{
m_LeftPressed = false;
}
void Player::stopRight()
{
m_RightPressed = false;
}
void Player::stopUp()
{
m_UpPressed = false;
}
void Player::stopDown()
{
m_DownPressed = false;
}
if (m_UpPressed)
{
m_Position.y -= m_Speed * elapsedTime;
}
if (m_DownPressed)
{
m_Position.y += m_Speed * elapsedTime;
}
if (m_RightPressed)
{
m_Position.x += m_Speed * elapsedTime;
}
if (m_LeftPressed)
{
m_Position.x -= m_Speed * elapsedTime;
}
m_Sprite.setPosition(m_Position);
m_Sprite.setRotation(angle);
}
void Player::upgradeSpeed()
{
// 20% speed upgrade
m_Speed += (START_SPEED * .2);
}
void Player::upgradeHealth()
{
// 20% max health upgrade
m_MaxHealth += (START_HEALTH * .2);
}
dx
-dy
-dx
#include<SFML/Graphics.hpp>
#include<iostream>
#include<cmath>
using namespace sf;
using namespace std;
int main()
{
VideoMode video(800, 600);
RenderWindow window(video, "Zombie Arena !!!");
Sprite spritePlayer;
Texture texturePlayer;
texturePlayer.loadFromFile("player.png");
spritePlayer.setTexture(texturePlayer);
FloatRect playerBound = spritePlayer.getLocalBounds();
spritePlayer.setOrigin(playerBound.width/2, playerBound.height/2);
float playerSpeed = 5;
float pixelPerSecPlayerX = window.getSize().x/ playerSpeed;
float pixelPerSecPlayerY = window.getSize().y/ playerSpeed;
Sprite spriteZombie;
Texture textureZombie;
textureZombie.loadFromFile("chaser.png");
spriteZombie.setTexture(textureZombie);
FloatRect zombieBound = spriteZombie.getLocalBounds();
spriteZombie.setOrigin(zombieBound.width/2, zombieBound.height/2);
float zombieSpeed = 7;
float pixelPerSecZombieX = window.getSize().x/ zombieSpeed;
float pixelPerSecZombieY = window.getSize().y/ zombieSpeed;
Clock ct;
Time dt;
spritePlayer.setPosition(window.getSize().x/2, window.getSize().y/2);
spriteZombie.setPosition(rand()%window.getSize().x,
rand()%window.getSize().y);
while(window.isOpen())
{
dt = ct.restart();
Event ev;
while(window.pollEvent(ev)){
if(ev.type == Event::Closed)
window.close();
}
spriteZombie.setPosition(zombieXY);
dx = playerXY.x - zombieXY.x;
dy = playerXY.y - zombieXY.y;
window.clear(Color::White);
window.draw(spritePlayer);
window.draw(spriteZombie);
window.display();
}
return(0);
}
Zombie Class
#pragma once
#include <SFML/Graphics.hpp>
#include <cmath>
class Zombie
{
private:
const float BLOATER_SPEED = 20;
const float CHASER_SPEED = 40;
const float CRAWLER_SPEED = 10;
Vector2f m_Position;
Sprite m_Sprite;
Texture m_Texture;
float m_Speed;
float m_Health;
bool m_Alive = false;
public:
FloatRect getPosition();
Sprite getSprite();
bool isAlive();
void spawn(float startX, float startY, int type, int seed);
void update(float elapsedTime, Vector2f playerLocation);
bool hit();
};
FloatRect Zombie::getPosition()
{
return m_Sprite.getGlobalBounds();
}
Sprite Zombie::getSprite()
{
return m_Sprite;
}
bool Zombie::isAlive()
{
return m_Alive;
}
void Zombie::spawn(float startX, float startY, int type, int seed)
{
m_Position.x = startX;
m_Position.y = startY;
// m_Sprite.setPosition(m_Position);
m_Sprite.setOrigin(25, 25);
switch (type)
{
case 0:
m_Texture.loadFromFile("bloater.png");
m_Sprite.setTexture(m_Texture);
m_Speed = BLOATER_SPEED;
m_Health = BLOATER_HEALTH;
m_Alive = true;
break;
case 1:
m_Texture.loadFromFile("chaser.png");
m_Sprite.setTexture(m_Texture);
m_Speed = CHASER_SPEED;
m_Health = CHASER_HEALTH;
m_Alive = true;
break;
case 2:
m_Texture.loadFromFile("crawler.png");
m_Sprite.setTexture(m_Texture);
m_Speed = CRAWLER_SPEED;
m_Health = CRAWLER_HEALTH;
m_Alive = true;
break;
}
srand((int)time(0) * seed);
float modifier = (rand() % (101 - 70) + 70);
modifier = modifier / 100;
m_Speed = m_Speed * modifier;
}
void Zombie::update(float elapsedTime, Vector2f playerLocation)
{
if (m_Alive)
{
float playerX = playerLocation.x;
float playerY = playerLocation.y;
if (m_Position.x < playerX)
{
m_Position.x = m_Position.x + m_Speed * elapsedTime;
}
if (m_Position.x > playerX)
{
m_Position.x = m_Position.x - m_Speed * elapsedTime;
}
if (m_Position.y < playerY)
{
m_Position.y = m_Position.y + m_Speed * elapsedTime;
}
if (m_Position.y > playerY)
{
m_Position.y = m_Position.y - m_Speed * elapsedTime;
}
m_Sprite.setPosition(m_Position);
float angle = (atan2(playerY - m_Position.y, playerX -
m_Position.x) * 180) / 3.141;
m_Sprite.setRotation(angle);
}
}
bool Zombie::hit()
{
m_Health--;
if (m_Health < 0)
{
m_Alive = false;
m_Texture.loadFromFile("blood.png");
m_Sprite.setTexture(m_Texture);
return true;
}
return false;
}
Bullet Movement Logic
a = y2 − y1
x2 − x1
g =
y2 − y1
For a:
2 2 2
a + b = M
2 2 2
⇒ (y2 − y1) + (x2 − x1) = M
2 2 2
(y2 − y1) + (x2 − x1) M
⇒ =
2 2
(y2 − y1) (y2 − y1)
2 2
(x2 − x1) M
⇒ 1 + =
2 2
(y2 − y1) (y2 − y1)
2
M
2
⇒ 1 + g =
2
(y2 − y1)
2
2
M
⇒ (y2 − y1) =
2
1 + g
M
⇒ y2 − y1 =
√ 1 + g2
M M
⇒ a = ≈
√ 1 + g2 1 + g
Similarly,
2 2 2
a + b = M
2 2 2
⇒ (y2 − y1) + (x2 − x1) = M
2 2 2
(y2 − y1) + (x2 − x1) M
⇒ =
2 2
(x2 − x1) (x2 − x1)
2 2
(y2 − y1) M
⇒ + 1 =
2 2
(x2 − x1) (x2 − x1)
2
1 M
⇒ + 1 =
2 2
g (x2 − x1)
2 2
1 + g M
⇒ =
g2 (x2 − x1)
2
2 2
2
M g
⇒ (x2 − x1) =
2
1 + g
M
⇒ x2 − x1 = g
√ 1 + g2
⇒ b = ag
Bullet Class
#pragma once
#include <SFML/Graphics.hpp>
#include <cmath>
using namespace sf;
class Bullet
{
private:
Vector2f m_Position;
RectangleShape m_BulletShape;
bool m_InFlight = false;
float m_BulletSpeed = 1000;
float m_BulletDistanceX;
float m_BulletDistanceY;
float m_XTarget;
float m_YTarget;
float m_MaxX;
float m_MinX;
float m_MaxY;
float m_MinY;
public:
Bullet();
void stop();
bool isInFlight();
void shoot(float startX, float startY, float xTarget, float yTarget);
FloatRect getPosition();
RectangleShape getShape();
void update(float elapsedTime);
};
Bullet::Bullet()
{
m_BulletShape.setSize(sf::Vector2f(2, 2));
}
void Bullet::shoot(float startX, float startY, float targetX, float
targetY)
{
m_InFlight = true;
m_Position.x = startX;
m_Position.y = startY;
float gradient = (startX - targetX) / (startY - targetY);
if (gradient < 0)
{
gradient *= -1;
}
m_BulletDistanceY = m_BulletSpeed / (1 + gradient);
m_BulletDistanceX = m_BulletSpeed * (gradient / (1 + gradient));
// float ratioXY = m_BulletSpeed / (1 + gradient);
// m_BulletDistanceY = m_BulletSpeed*(1/1+;m_BulletDistanceX =
ratioXY * gradient;
if (targetX < startX)
{
m_BulletDistanceX *= -1;
}
bool Bullet::isInFlight()
{
return m_InFlight;
}
FloatRect Bullet::getPosition()
{
return m_BulletShape.getGlobalBounds();
}
RectangleShape Bullet::getShape()
{
return m_BulletShape;
}
public:
Pickup(int type);
FloatRect getPosition();
Sprite getSprite();
void spawn();
bool isSpawned();
void update(float elapsedTime);
void setArena(IntRect arena);
void upgrade();
int gotIt();
};
Pickup::Pickup(int type)
{
m_Type = type;
if (m_Type == 1)
{ // HEALTH
m_Texture.loadFromFile("health_pickup.png");
m_Sprite.setTexture(m_Texture);
m_Value = HEALTH_START_VALUE;
}
else
{
m_Texture.loadFromFile("ammo_pickup.png");
m_Sprite.setTexture(m_Texture);
m_Value = AMMO_START_VALUE;
}
m_Sprite.setOrigin(25, 25);
m_SecondsToLive = START_SECONDS_TO_LIVE;
m_SecondsToWait = START_WAIT_TIME;
}
void Pickup::setArena(IntRect arena)
{
m_Arena.left = arena.left + 50;
m_Arena.top = arena.top + 50;
m_Arena.width = arena.width - 50;
m_Arena.height = arena.height - 50;
spawn();
}
FloatRect Pickup::getPosition()
{
return m_Sprite.getGlobalBounds();
}
Sprite Pickup::getSprite()
{
return m_Sprite;
}
bool Pickup::isSpawned()
{
return m_Spawned;
}
void Pickup::spawn()
{
srand((int)time(0) / m_Type);
m_Position.x = rand() % m_Arena.width;
srand((int)time(0) * m_Type);
m_Position.y = rand() % m_Arena.height;
m_Sprite.setPosition(m_Position);
m_SecondsSinceSpawn = 0;
m_Spawned = true;
}
void Pickup::update(float elapsedTime)
{
if (m_Spawned)
{
m_SecondsSinceSpawn = m_SecondsSinceSpawn + elapsedTime;
}
else
{
m_SecondsSinceDeSpawn = m_SecondsSinceDeSpawn + elapsedTime;
}
if (m_SecondsSinceDeSpawn > m_SecondsToWait && !m_Spawned)
{
spawn();
}
if (m_SecondsSinceSpawn > m_SecondsToLive && m_Spawned)
{
m_Spawned = false;
m_SecondsSinceDeSpawn = 0;
}
}
int Pickup::gotIt()
{
m_Spawned = false;
m_SecondsSinceDeSpawn = 0;
return m_Value;
}
void Pickup::upgrade()
{
if (m_Type == 1)
{
m_Value += (HEALTH_START_VALUE * 0.5);
}
else
{
m_Value += (AMMO_START_VALUE * 0.5);
}
m_SecondsToLive += START_SECONDS_TO_LIVE / 10;
m_SecondsToWait -= START_WAIT_TIME / 10;
}
Zombie Arena Game
#include <SFML/Graphics.hpp>
#include <iostream>
#include "Player.cpp"
#include "zombie.cpp"
#include "bullet.cpp"
#include "pickup.cpp"
#include <sstream>
using namespace sf;
int createBackground(VertexArray &rVA, IntRect arena);
Zombie *createHorde(int numZombies, IntRect arena);
int main()
{
int wave = 0;
// The game will always be in one of four states
enum class State
{
PAUSED,
LEVELING_UP,
GAME_OVER,
PLAYING,
NEXTWAVE
};
// Start with the GAME_OVER state
State state = State::GAME_OVER;
// Get the screen resolution and create an SFML window
Vector2f resolution;
// resolution.x = VideoMode::getDesktopMode().width;
// resolution.y = VideoMode::getDesktopMode().height;
resolution.x = 1920;
resolution.y = 1080;
RenderWindow window(VideoMode(800, 600),
"Zombie Arena", Style::Fullscreen);
Bullet bullets[100];
int currentBullet = 0;
int bulletsSpare = 24;
int bulletsInClip = 6;
int clipSize = 6;
float fireRate = 3;
Time lastPressed;
// Here is our clock for timing everything
Clock clock;
// How long has the PLAYING state been active
Time gameTimeTotal;
int score = 0;
int hiScore = 0;
Pickup healthPickup(1);
Pickup ammoPickup(2);
// For the home/game over screen
Sprite spriteGameOver;
Texture textureGameOver;
textureGameOver.loadFromFile("background.png");
spriteGameOver.setTexture(textureGameOver);
spriteGameOver.setPosition(0, 0);
// Paused
Text pausedText;
pausedText.setFont(font);
pausedText.setCharacterSize(155);
pausedText.setFillColor(Color::White);
pausedText.setPosition(400, 400);
pausedText.setString("Press Enter \nto continue");
// Game Over
Text gameOverText;
gameOverText.setFont(font);
gameOverText.setCharacterSize(125);
gameOverText.setFillColor(Color::White);
gameOverText.setString("Press Enter to play");
FloatRect gameOverTextRect = gameOverText.getLocalBounds();
gameOverText.setOrigin(gameOverTextRect.width / 2,
gameOverTextRect.height / 2);
gameOverText.setPosition(gameOverView.getSize().x / 2,
gameOverView.getSize().y / 2);
// Levelling up
Text levelUpText;
levelUpText.setFont(font);
levelUpText.setCharacterSize(80);
levelUpText.setFillColor(Color::White);
levelUpText.setPosition(150, 250);
std::stringstream levelUpStream;
levelUpStream << "0- Start the normal game"
<< "\n1- Increased rate of fire"
<< "\n2- Increased clip size(next reload)"
<< "\n3- Increased max health"
<< "\n4- Increased run speed"
<< "\n5- More and better health pickups"
<< "\n6- More and better ammo pickups";
levelUpText.setString(levelUpStream.str());
// Ammo
Text ammoText;
ammoText.setFont(font);
ammoText.setCharacterSize(55);
ammoText.setFillColor(Color::White);
ammoText.setPosition(200, 980);
// Score
Text scoreText;
scoreText.setFont(font);
scoreText.setCharacterSize(55);
scoreText.setFillColor(Color::White);
scoreText.setPosition(20, 0);
// Hi Score
Text hiScoreText;
hiScoreText.setFont(font);
hiScoreText.setCharacterSize(55);
hiScoreText.setFillColor(Color::White);
hiScoreText.setPosition(1400, 0);
std::stringstream s;
s << "Hi Score:" << hiScore;
hiScoreText.setString(s.str());
// Zombies remaining
Text zombiesRemainingText;
zombiesRemainingText.setFont(font);
zombiesRemainingText.setCharacterSize(55);
zombiesRemainingText.setFillColor(Color::White);
zombiesRemainingText.setPosition(1500, 980);
zombiesRemainingText.setString("Zombies: 100");
Text waveNumberText;
waveNumberText.setFont(font);
waveNumberText.setCharacterSize(55);
waveNumberText.setFillColor(Color::White);
waveNumberText.setPosition(1250, 980);
waveNumberText.setString("Wave: 0");
// Health bar
RectangleShape healthBar;
healthBar.setFillColor(Color::Red);
healthBar.setPosition(450, 980);
if (state == State::PLAYING)
{
if (event.key.code == Keyboard::R)
{
if (bulletsSpare >= clipSize)
{
// Plenty of bullets. Reload.
bulletsInClip = clipSize;
bulletsSpare -= clipSize;
}
else if (bulletsSpare > 0)
{
// Only few bullets left
bulletsInClip = bulletsSpare;
bulletsSpare = 0;
}
else
{
// More here soon?!
}
}
}
}
// Handle the levelling up state
if (state == State::LEVELING_UP)
{
// Handle the player levelling up
if (event.key.code == Keyboard::Num0)
{
state = State::NEXTWAVE;
}
if (event.key.code == Keyboard::Num1)
{
fireRate++;
state = State::NEXTWAVE;
}
if (event.key.code == Keyboard::Num2)
{
clipSize += clipSize;
state = State::NEXTWAVE;
}
if (event.key.code == Keyboard::Num3)
{
player.upgradeHealth();
state = State::NEXTWAVE;
}
if (event.key.code == Keyboard::Num4)
{
player.upgradeSpeed();
state = State::NEXTWAVE;
}
if (event.key.code == Keyboard::Num5)
{
healthPickup.upgrade();
state = State::NEXTWAVE;
}
if (event.key.code == Keyboard::Num6)
{
ammoPickup.upgrade();
state = State::NEXTWAVE;
}
} // End levelling up
} // End event polling
if (Keyboard::isKeyPressed(Keyboard::S))
{
player.moveDown();
}
else
{
player.stopDown();
}
if (Keyboard::isKeyPressed(Keyboard::A))
{
player.moveLeft();
}
else
{
player.stopLeft();
}
if (Keyboard::isKeyPressed(Keyboard::D))
{
player.moveRight();
}
else
{
player.stopRight();
}
// Fire a bullet
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
if (gameTimeTotal.asMilliseconds() -
lastPressed.asMilliseconds() > 1000 / fireRate && bulletsInClip > 0)
{
currentBullet++;
if (currentBullet > 99)
{
currentBullet = 0;
}
lastPressed = gameTimeTotal;
bulletsInClip--;
}
}
/*
****************
UPDATE THE FRAME
****************
*/
if (state == State::PLAYING)
{
// Update the delta time
Time dt = clock.restart();
// Update the total game time
gameTimeTotal += dt;
// Make a decimal fraction of 1 from the delta time
float dtAsSeconds = dt.asSeconds();
numZombiesAlive--;
if (player.hit(gameTimeTotal))
{
// More here later
}
if (player.getHealth() <= 0)
{
state = State::GAME_OVER;
}
}
}
if
(player.getPosition().intersects(healthPickup.getPosition()) &&
healthPickup.isSpawned())
{
player.increaseHealthLevel(healthPickup.gotIt());
}
/*
**************
Draw the scene
**************
*/
window.clear();
window.setMouseCursorVisible(false);
if (state == State::PLAYING)
{
// Draw pickup
if (ammoPickup.isSpawned())
{
window.draw(ammoPickup.getSprite());
}
if (healthPickup.isSpawned())
{
window.draw(healthPickup.getSprite());
}
window.setView(hudView);
window.draw(healthBar);
window.draw(spriteAmmoIcon);
window.draw(ammoText);
window.draw(scoreText);
window.draw(hiScoreText);
window.draw(waveNumberText);
window.draw(zombiesRemainingText);
} // end of draw while playing
if (state == State::LEVELING_UP)
{
window.setView(gameOverView);
window.draw(spriteGameOver);
window.draw(levelUpText);
}
if (state == State::PAUSED)
{
window.setView(gameOverView);
window.draw(pausedText);
}
if (state == State::GAME_OVER)
{
window.setView(gameOverView);
window.draw(spriteGameOver);
window.draw(gameOverText);
}
window.display();
return 0;
}
int createBackground(VertexArray &rVA, IntRect arena)
{
// Anything we do to rVA we are actually doing to background (in the
main function)
return TILE_SIZE;
}
#include<iostream>
int main()
{
std::cout << "Hello World!!" << std::endl;
return(0);
}
or
#include<iostream>
using namespace std;
int main()
{
cout << "Hello World!!" << endl;
return(0);
}
#include <iostream>
using namespace std;
int lcm(int m, int n, int a)
{
if((a%m == 0) && (a%n ==0))
return(a);
else
return(lcm(m,n, a+n));
}
int main()
{
int m, n;
cout << "Enter the 1st Num :";
cin >> m;
cout << "Enter the 2nd Num :";
cin >> n;
cout << "LCM of " << m << " & " << n << "is : " << lcm(m,n,n) <<
endl;
return(0);
}
WAP to get 5 student details using structure and print on the
screen
//WAP to get 5 student details using structure and print on the screen
#include<iostream>
#include<iomanip>
using namespace std;
struct student
{
char name[30];
int roll;
float cgpa;
};
int main()
{
struct student s[5];
for(int i=0;i<5;i++)
{
cout << "Name of " << i << "th student : ";
if(i!=0)
cin.ignore();
cin.getline(s[i].name, 30);
cout << "Roll of " << i << "th student : ";
cin >> s[i].roll;
cout << "cgpa of " << i << "th student : ";
cin >> s[i].cgpa;
}
#include<iostream>
using namespace std;
class student{
int id;
char name[30];
float cgpa;
void getdata()
{
cout << "Eneter id : ";
cin >> id;
cout << "Enter name : ";
cin.ignore();
cin.getline(name, 30);
cout << "Enter the CGPA : ";
cin >> cgpa;
}
void printdata()
{
cout << "Name : " << name << endl;
cout << "ID : " << id << endl;
cout << "CGPA : " << cgpa << endl;
}
void changecgpa()
{
cout << "Enter new CGPA : ";
cin >> cgpa;
}
public:
void driver()
{
int i;
cout << "Enter 1 : for entring information " << endl;
cout << "Enter 2 : for showing information " << endl;
cout << "Enter 3 : for changing cgpa value " << endl;
cout << "enter your choice :";
cin >> i;
switch(i)
{
case 1: getdata(); break;
case 2: printdata(); break;
case 3: changecgpa(); break;
default: cout << "Wrong Choice ...." << endl;
}
}
};
int main()
{
student s1;
for(int i=0;i<4;i++)
s1.driver();
return(0);
}
#include<iostream>
using namespace std;
class student{
int id;
char name[30];
float cgpa;
void getdata()
{
cout << "Eneter id : ";
cin >> id;
cout << "Enter name : ";
cin.ignore();
cin.getline(name, 30);
cout << "Enter the CGPA : ";
cin >> cgpa;
}
void printdata()
{
cout << "Name : " << name << endl;
cout << "ID : " << id << endl;
cout << "CGPA : " << cgpa << endl;
}
void changecgpa()
{
cout << "Enter new CGPA : ";
cin >> cgpa;
}
public:
void driver(int i)
{
switch(i)
{
case 1: getdata(); break;
case 2: printdata(); break;
case 3: changecgpa(); break;
default: cout << "Wrong Choice ...." << endl;
}
}
};
int main()
{
int n;
cout >> "Enter the number of students : ";
cin << n;
student s[n];
// Store the details
for(int i=0;i<n;i++)
s[i].driver(1);
// Show the details
for(int i=0;i<n;i++)
s[i].driver(2);
return(0);
}
#include<iostream>
using namespace std;
struct item{
char ItemName[20];
float ItemCost;
int ItemCount;
};
class cart
{
private:
int n;
item *itm;
float TotalCost;
public:
void getdata()
{
cout << "Enter the number of item :";
cin >> n;
itm = new item[n];
}
void getItemDetails()
{
for(int i=0;i<n;i++)
{
cout << "Item Name : ";
cin.ignore();
cin.getline(itm[i].ItemName,20);
cout << "Item Cost : ";
cin >> itm[i].ItemCost;
cout << "Item count : ";
cin >> itm[i].ItemCount;
}
}
void calculatePrice()
{
TotalCost = 0;
for(int i=0;i<n;i++)
{
TotalCost = TotalCost + (itm[i].ItemCost * itm[i].ItemCount);
}
cout << "Total cost : " << TotalCost << endl;
}
};
int main()
{
cart c1;
c1.getdata();
c1.getItemDetails();
c1.calculatePrice();
return(0);
}
#include <iostream>
#include <cstring>
using namespace std;
class BankAccount {
private:
char accountHolder[30];
int accountNumber;
double balance;
public:
// Defining default constructor
BankAccount()
{
cout << "Acount creation process stared ... "<<endl;
}
// Constructor to initialize account details
BankAccount(char *name, int accNum, double initialBalance) {
strcpy(accountHolder,name);
accountNumber = accNum;
balance = initialBalance;
cout << "Account created successfully!" << endl;
cout << "Account Holder: " << accountHolder << endl;
cout << "Account Number: " << accountNumber << endl;
cout << "Initial Balance: " << balance << endl;
}
int main() {
// Creating an account
BankAccount acc("Dibyasundar Das", 101, (double)(5000.0));
acc.deposit(2000);
acc.withdraw(1500);
acc.display();
// Account goes out of scope here, triggering destructor
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
class LibraryBook {
private:
char title[100];
char author[100];
char borrower[100];
public:
// Constructor to initialize book details
LibraryBook(const char* bookTitle, const char* bookAuthor, const
char* borrowerName) {
strcpy(title, bookTitle);
strcpy(author, bookAuthor);
strcpy(borrower, borrowerName);
int main() {
int choice;
LibraryBook *book1;
while(1)
{
cout << "Press 1 : Issue a book "<<endl;
cout << "Press 2 : Return a book "<<endl;
cin >> choice;
// Borrowing a book
if (choice ==1)
{
book1 = new LibraryBook("Wings of Fire",
" Arun Tiwari", "Dibyasundar Das");
}
else
{
delete book1;
}
}
return 0;
}
inr main()
{
VideoMode video(800,600);
RenderWindow window(video, "Window!");
while(window.isOpen())
{
window.clear();
window.display();
}
}
OR
while(window.isOpen())
{
if(Keyboard::isKeyPressed(Keyboard::Escape))
{
window.close();
}
}
GPWC Quizzes
Quiz 001 2025 6th Sem (Sec : 2241001)
1. Which of the following is the correct syntax for a class in C++?
A. class MyClass { int a; };
B. MyClass { class int a; };
C. def class MyClass { int a; };
D. create MyClass { int a; };
2. What is cout ?
A. It is a function
B. It is a class
C. It is an object (class instance)
D. It is a reserved word (C++ keyword)
Answer: D. 1
4.
Answer: B. 1 0
5.
Answer: C. 2
6.
class MyClass{
public:
~MyClass() {
cout<<"My destructor"<<endl;
}
};
void main()
{
MyClass obj;
obj.~MyClass();
}
Answer: B.
My destructor
My destructor
7.
class Sample {
public:
Sample(int x = 10) {
cout << "Value: " << x << endl;
}
};
int main() {
Sample obj;
return 0;
}
Answer: B. Value: 10
Answer: B. Inheritance
10. Null character needs a space of
A. zero bytes
B. one byte
C. three bytes
D. four bytes
11.
void Cube(double y) {
y = y*y*y;
}
void main()
{
double g = 4.0;
Cube(g);
cout << g<<endl;
return(0);
}
Answer: A. 4
12.
Answer: B. 64
Answer: A. >>
15. When struct is used instead of the keyword class means, what will happen in
the program?
A. access is public by default
B. access is private by default
C. access is protected by default
D. none of the mentioned
Answer: B. 2
2. Which operator is used to allocate memory dynamically in C++?
A. malloc
B. new
C. alloc
D. create
Answer: B. new
Answer: D. 1
4.
int main() {
float a = 5, b = 2;
cout << a / b;
return 0;
}
Answer: A. 2.5
5.
int main() {
int x = 10;
int &y = x;
y = 20;
cout << x;
return 0;
}
Answer: B. 20
6.
int main() {
int x = 5;
cout << (x << 1);
return 0;
}
Answer: B. 10
7.
class Test {
public:
int x;
};
int main() {
Test obj;
cout << obj.x;
return 0;
}
class Sample {
public:
Sample(int x = 10) {
cout << "Value: " << x << endl;
}
};
int main() {
Sample obj;
return 0;
}
Answer: B. Value: 10
Answer: B. Inheritance
11.
class MyClass {
public:
MyClass() {cout << "MyClass ";}
~MyClass() {cout << "~MyClass ";}
};
void myFunc() { MyClass obj;}
int main() {
myFunc();
cout << "Main ";
return 0;
}
13.
void Cube(double y) {
y = y*y*y;
}
int main()
{
double g = 4.0;
Cube(g);
cout << g<<endl;
return(0);
}
Answer: A. 4
14.
Answer: B. 64
15.
class A {
public:
A() { cout << "A "; }
~A() { cout << "~A "; }
};
void func() {
static A obj;
}
int main() {
func();
func();
cout << "Main ";
return 0;
}
Answer: C. A Main ~A
Answer: B. False
Quiz 002 2025 6th Sem (Sec : 2241001)
WAP program to create a game with following objectives
1. There is a basket at bottom which can only move left and right.
2. There are 2 types of balls coming from the top to down in a straight line, namely Red
Balls and White Balls.
3. The ratio of red to white ball is 6:1 where Red Ball are unsafe and White Ball as safe
to collect.
4. The gamer has to collect White Ball while avoiding the Red Balls. Each successful
collection will increase the score by 1.
5. There is a time bar which indicate the elapsed time. With every success in collecting
the white ball the gamer will be rewarded with additional time.
6. Goal is to collect as many as white Ball Possible without touching Red Ball and before
time runs out.
7. You have to implement 2 HUD
1. Score counter
2. Time Bar
8. Additionally Game should be paused and un-paused with space and the game can be
restarted with Enter Key.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
int main()
{
VideoMode video(800, 600);
RenderWindow window(video, "Catch Ball Game");
window.setView(view);
RectangleShape batShape;
float batWidth = 200;
float batHeight = 10;
float batSpeed = 2;
float batPixSec = windowHeight / batSpeed;
batShape.setOrigin(batWidth / 2, batHeight / 2);
batShape.setSize(Vector2f(batWidth, batHeight));
batShape.setFillColor(Color::White);
batShape.setPosition(windowWidth / 2, windowHeight - 20);
CircleShape ballShape;
float radius = 20;
float ballSpeed = 3;
float ballPixSecX = windowWidth / ballSpeed;
float ballPixSecY = windowHeight / ballSpeed;
ballShape.setRadius(radius);
ballShape.setFillColor(Color::Magenta);
ballShape.setPosition(20 + rand() % (int)(windowWidth - 20), -100);
CircleShape ballEnemyShape[6];
for (int i = 0; i < 6; i++)
{
ballEnemyShape[i].setRadius(radius);
ballEnemyShape[i].setFillColor(Color::Red);
float x = 20 + rand() % (int)(windowWidth - 20);
float y = -200 + rand() % 200;
ballEnemyShape[i].setPosition(x, y);
}
Font font;
font.loadFromFile("KOMIKAP_.ttf");
Text scoreText;
scoreText.setFont(font);
scoreText.setCharacterSize(75);
scoreText.setFillColor(Color::White);
scoreText.setPosition(20, 20);
Text liveText;
liveText.setFont(font);
liveText.setCharacterSize(75);
liveText.setFillColor(Color::White);
float scoreVal = 0;
float liveVal = 3;
Clock ct;
Time dt;
while (window.isOpen())
{
dt = ct.restart();
Event ev;
while (window.pollEvent(ev))
{
if (ev.type == Event::Closed || (ev.type == Event::KeyPressed
&& ev.key.code == Keyboard::Escape))
window.close();
if (ev.type == Event::KeyPressed && ev.key.code ==
Keyboard::Enter && gameOver)
{
paused = false;
gameOver = false;
bounceTop = false;
bounceBottom = true;
scoreVal = 0;
liveVal = 3;
ballShape.setPosition(windowWidth / 2, 20);
}
}
if (!gameOver)
ss1 << "Lives : " << liveVal;
else
ss1 << "Game Over .. Press Enter to restart";
liveText.setString(ss1.str());
if (!paused)
{
if (Keyboard::isKeyPressed(Keyboard::Left))
{
float x = batShape.getPosition().x;
float y = batShape.getPosition().y;
x = x - dt.asSeconds() * batPixSec;
if (x < batWidth / 2)
x = batWidth / 2;
batShape.setPosition(x, y);
}
if (Keyboard::isKeyPressed(Keyboard::Right))
{
float x = batShape.getPosition().x;
float y = batShape.getPosition().y;
x = x + dt.asSeconds() * batPixSec;
if (x > windowWidth - batWidth / 2)
x = windowWidth - batWidth / 2;
batShape.setPosition(x, y);
}
float x = ballShape.getPosition().x;
float y = ballShape.getPosition().y;
y = y + ballPixSecY * dt.asSeconds();
if (y > view.getSize().y)
{
y = -40;
x = 20 + rand() % (int)(view.getSize().x - 40);
}
ballShape.setPosition(x, y);
if
(ballShape.getGlobalBounds().intersects(batShape.getGlobalBounds()))
{
ballShape.setPosition(20 + rand() % (int)
(view.getSize().x - 40), -40);
scoreVal ++;
}
for (int i = 0; i < 6; i++)
{
if
(ballEnemyShape[i].getGlobalBounds().intersects(batShape.getGlobalBounds(
)))
{
ballEnemyShape[i].setPosition(20 + rand() % (int)
(view.getSize().x - 40), -40);
liveVal -- ;
}
}
}
if (liveVal == 0)
{
paused = true;
gameOver = true;
ballShape.setPosition(windowWidth / 2, windowHeight / 2);
}
window.clear();
window.draw(batShape);
window.draw(ballShape);
for (int i = 0; i < 6; i++)
{
window.draw(ballEnemyShape[i]);
}
window.draw(scoreText);
window.draw(liveText);
window.display();
}
}
Quiz 002 2025 6th Sem (Sec : 2241002)
WAP program to create a game with following objectives
1. Design and implement a 2D car racing game using C++ and the SFML (Simple and
Fast Multimedia Library) framework.
2. In this game, the player will control a car that moves left and right on a vertically
scrolling road, avoiding enemy cars that approach from the top of the screen.
3. The game should include real-time player input handling, enemy spawning, collision
detection, scorekeeping, and a game-over scenario when a collision occurs.
4. Enemy cars spawn from the top and move downward. Avoid collisions with enemy car.
Increase the speed of enemy cars as time progresses for difficulty.
5. The background should scroll to simulate forward motion, and the difficulty should
increase over time by making enemy cars move faster.
6. The game must also display the current score on the screen, and after a collision,
show a “Game Over” screen with the final score and an option to restart the game.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
using namespace sf;
using namespace std;
int main()
{
VideoMode video(200, 600);
RenderWindow window(video, "CarGame", Style::Titlebar |
Style::Close);
RectangleShape divider[11];
for (int i = 0; i < 11; i++)
{
divider[i].setSize(Vector2f(10, 50));
divider[i].setPosition(95, -60 + (i * 60));
divider[i].setFillColor(Color::White);
}
float dividerSpeed = 5;
float diviserPixelPerSec = 600 / dividerSpeed;
RectangleShape carDrive;
carDrive.setSize(Vector2f(30, 50));
carDrive.setFillColor(Color::White);
carDrive.setPosition(40, 540);
float carSpeed = 1;
float carPixelPerSec = 200 / carSpeed;
RectangleShape enemyCar[7];
for (int i = 0; i < 7; i++)
{
enemyCar[i].setSize(Vector2f(30, 50));
float x = rand() % 170;
if (rand() % 3 != 0)
enemyCar[i].setPosition(x, -900 + (i * 150));
else
enemyCar[i].setPosition(210, -900 + (i * 150));
enemyCar[i].setFillColor(Color::Red);
}
float enemyCarPixelPerSec = 60;
Clock ct;
Time dt;
Text scoreHud;
Text speedHud;
Text message;
Font ft;
ft.loadFromFile("KOMIKAP_.ttf");
scoreHud.setFont(ft);
scoreHud.setFillColor(Color::White);
scoreHud.setCharacterSize(12);
scoreHud.setString("Score : 0");
scoreHud.setPosition(20, 20);
speedHud.setFont(ft);
speedHud.setFillColor(Color::White);
speedHud.setCharacterSize(12);
speedHud.setString("Speed : 1");
FloatRect speedHudBound = speedHud.getLocalBounds();
speedHud.setPosition(window.getSize().x - 20 - speedHudBound.width,
20);
message.setFont(ft);
message.setFillColor(Color::White);
message.setCharacterSize(20);
message.setString("");
FloatRect messageHudBound = message.getLocalBounds();
message.setOrigin(messageHudBound.width / 2, messageHudBound.height /
2);
message.setPosition(window.getSize().x / 2, window.getSize().y / 2);
while (window.isOpen())
{
dt = ct.restart();
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
{
window.close();
}
if (event.type == Event::KeyReleased)
{
acceptInput = true;
}
if (event.type == Event::KeyPressed)
{
if (event.key.code == Keyboard::Enter && gameOver)
{
paused = false;
gameOver = false;
score = 0;
enemyCarPixelPerSec = 60;
gameSpeed = 1;
for (int i = 0; i < 7; i++)
{
enemyCar[i].setSize(Vector2f(30, 50));
float x = rand() % 170;
if (rand() % 3 == 0)
enemyCar[i].setPosition(x, -900 + (i * 150));
else
enemyCar[i].setPosition(210, -900 + (i *
150));
enemyCar[i].setFillColor(Color::Red);
}
message.setString("");
messageHudBound = message.getLocalBounds();
message.setOrigin(messageHudBound.width / 2,
messageHudBound.height / 2);
message.setPosition(window.getSize().x / 2,
window.getSize().y / 2);
acceptInput = false;
}
}
}
if(Keyboard::isKeyPressed(Keyboard::Space) && acceptInput)
{
paused = !paused;
acceptInput = false;
}
if (!paused)
{
if (Keyboard::isKeyPressed(Keyboard::Left))
{
float x = carDrive.getPosition().x;
float y = carDrive.getPosition().y;
x = x - dt.asSeconds() * carPixelPerSec;
if (x < 0)
x = 0;
carDrive.setPosition(x, y);
}
if (Keyboard::isKeyPressed(Keyboard::Right))
{
float x = carDrive.getPosition().x;
float y = carDrive.getPosition().y;
x = x + dt.asSeconds() * carPixelPerSec;
if (x > 170)
x = 170;
carDrive.setPosition(x, y);
}
if (gameOver)
{
paused = true;
message.setString("Game Over !!!");
messageHudBound = message.getLocalBounds();
message.setOrigin(messageHudBound.width / 2,
messageHudBound.height / 2);
message.setPosition(window.getSize().x / 2,
window.getSize().y / 2);
}
else if(paused && !gameOver)
{
message.setString("Paused !!!");
messageHudBound = message.getLocalBounds();
message.setOrigin(messageHudBound.width / 2,
messageHudBound.height / 2);
message.setPosition(window.getSize().x / 2,
window.getSize().y / 2);
}
else
{
message.setString("");
messageHudBound = message.getLocalBounds();
message.setOrigin(messageHudBound.width / 2,
messageHudBound.height / 2);
message.setPosition(window.getSize().x / 2,
window.getSize().y / 2);
}
window.clear();
window.draw(carDrive);
window.draw(scoreHud);
window.draw(speedHud);
window.draw(message);
window.display();
}
return (0);
}