TABLE OF CONTENT (TOC)
Serial
Sub-topic Page
number
number
1 ACKNOWLEDGEMENT
2 INTRODUCTION
3 AIM
4 SOURCE CODE
5 OUTPUT
6 BIBLIOGRAPHY
Introduction
The project titled “2D Shooter Game” is a Python-based arcade-style shooting game developed using the
Pygame library. This game simulates a battle scenario in a 2D top-down environment, where the player
competes against multiple computer-controlled bots in a map filled with obstacles such as houses and vehicles.
The game begins with a lobby, where the player can start the match by clicking a button. Upon starting, the
player is spawned into the map along with 29 AI-controlled bots, making a total of 30 participants in the
battle. The player has 200 health points and can navigate using WASD keys, aim with the mouse, and shoot
enemies to eliminate them. Each enemy kill rewards the player with 10 coins, and the last player standing
receives a bonus of 100 coins.
The game features basic AI mechanics, where bots can wander, chase the player, and shoot if they are within
range. The map contains houses and vehicles that serve as cover and obstacles, adding strategic depth to
gameplay. The player’s perspective is centered on the character, providing a first-person-style experience in a
2D environment.
This project demonstrates key concepts of game development, including player and enemy mechanics,
collision detection, health and scoring systems, and the creation of interactive game environments. It also
serves as a foundation for further enhancements, such as improved AI, additional weapons, or multiplayer
functionality.
AIM
The aim of this project is to design and develop
an interactive 2D shooting game that allows
players to control a character, navigate a map,
and engage in combat scenarios. The game
focuses on enhancing problem-solving skills,
hand-eye coordination, and strategic thinking
while providing an entertaining and immersive
gaming experience. Additionally, this project
aims to demonstrate practical knowledge of
Python programming, game development
concepts, and the use of libraries such as
Pygame for creating engaging visual and
interactive content.
SOURCE CODE
2D Shooter Game (Pygame)
Features:
- Lobby with Start button
- Map with houses (rectangles) and vehicles (rectangles)
- Player (centered camera) and 29 bot enemies
- Player has 200 health
- Each kill awards player 10 coins; if player is last one standing, award 100 coins
- When player dies, returns to lobby and resets
- Simple bot AI: wander, detect player within range to chase and shoot
- Basic bullets, collisions, respawn to lobby
Controls:
- WASD: move
- Mouse: aim
- Left click: shoot
- R: reload (not strictly necessary)
- Esc: quit
Save this file as 2D_Shooter_Game.py and run with `python 2D_Shooter_Game.py`
Requires: pygame (pip install pygame)
This is a compact, single-file prototype. It is NOT a full production game but provides
the requested mechanics and a good base for further development.
"""
import math
import random
import pygame
from [Link] import Vector2
# --- Config ---
SCREEN_W, SCREEN_H = 1280, 720
MAP_W, MAP_H = 3000, 2000
FPS = 60
NUM_BOTS = 29
PLAYER_MAX_HEALTH = 200
BULLET_SPEED = 900.0
BULLET_LIFETIME = 1.8
BOT_BULLET_SPEED = 700.0
KILL_COINS = 10
WIN_BONUS = 100
# Colors
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (200,30,30)
GREEN = (30,200,30)
BLUE = (30,144,255)
YELLOW = (240,200,20)
GRAY = (120,120,120)
[Link]()
FONT = [Link]('Arial', 20)
BIGFONT = [Link]('Arial', 48)
screen = [Link].set_mode((SCREEN_W, SCREEN_H))
clock = [Link]()
# --- Utility ---
def clamp(v, a, b):
return max(a, min(b, v))
# --- Entities ---
class Bullet:
def __init__(self, pos, vel, owner, damage=20, life=BULLET_LIFETIME):
[Link] = Vector2(pos)
[Link] = Vector2(vel)
[Link] = owner # 'player' or Bot instance
[Link] = damage
[Link] = life
def update(self, dt):
[Link] += [Link] * dt
[Link] -= dt
return [Link] > 0 and 0 <= [Link].x <= MAP_W and 0 <= [Link].y <= MAP_H
def draw(self, surf, cam):
p = world_to_screen([Link], cam)
[Link](surf, YELLOW, (int(p.x), int(p.y)), 4)
class Actor:
def __init__(self, pos, color, health=100):
[Link] = Vector2(pos)
[Link] = Vector2(0,0)
[Link] = color
[Link] = health
self.max_health = health
[Link] = 18
[Link] = True
def take_damage(self, d, attacker=None):
if not [Link]: return
[Link] -= d
if [Link] <= 0:
[Link] = False
def draw_healthbar(self, surf, cam):
p = world_to_screen([Link] + Vector2(0,-30), cam)
w = 40
h=6
rect_bg = [Link](p.x - w//2, p.y - h//2, w, h)
rect_fg = [Link](p.x - w//2, p.y - h//2, w * ([Link]/self.max_health), h)
[Link](surf, RED, rect_bg)
[Link](surf, GREEN, rect_fg)
class Player(Actor):
def __init__(self, pos):
super().__init__(pos, BLUE, health=PLAYER_MAX_HEALTH)
[Link] = 0
[Link] = 0
[Link] = 340
self.fire_rate = 0.15
self.time_since_shot = 0
def update(self, dt, keys, mouse_world):
# Movement
dir = Vector2(0,0)
if keys[pygame.K_w]: dir.y -= 1
if keys[pygame.K_s]: dir.y += 1
if keys[pygame.K_a]: dir.x -= 1
if keys[pygame.K_d]: dir.x += 1
if dir.length_squared() > 0:
dir = [Link]()
[Link] = dir * [Link]
[Link] += [Link] * dt
[Link].x = clamp([Link].x, 0, MAP_W)
[Link].y = clamp([Link].y, 0, MAP_H)
self.time_since_shot += dt
def can_shoot(self):
return self.time_since_shot >= self.fire_rate
def shoot(self, target):
if not self.can_shoot(): return None
self.time_since_shot = 0
dir = (Vector2(target) - [Link])
if dir.length_squared() == 0: dir = Vector2(1,0)
dir = [Link]()
vel = dir * BULLET_SPEED
b = Bullet([Link] + dir*28, vel, 'player', damage=35)
return b
def draw(self, surf, cam, mouse_world):
p = world_to_screen([Link], cam)
# body
[Link](surf, [Link], (int(p.x), int(p.y)), [Link])
# direction line (aim)
dir = (Vector2(mouse_world) - [Link])
if dir.length_squared()>0:
dir = [Link]()
end = p + Vector2(dir.x, dir.y)*30
[Link](surf, WHITE, (p.x,p.y),(end.x,end.y),3)
self.draw_healthbar(surf, cam)
class Bot(Actor):
def __init__(self, pos):
super().__init__(pos, RED, health=120)
[Link] = [Link](120,220)
self.fire_rate = [Link](0.6,1.6)
self.time_since_shot = [Link](0, self.fire_rate)
[Link] = None
self.wander_dir = Vector2([Link](-1,1), [Link](-1,1))
if self.wander_dir.length_squared() == 0:
self.wander_dir = Vector2(1,0)
self.wander_dir = self.wander_dir.normalize()
def update(self, dt, player):
if not [Link]: return
# Simple AI: if close to player chase; if very close shoot
to_player = [Link] - [Link]
dist = to_player.length()
if dist < 450:
# chase
if dist>60:
[Link] = to_player.normalize() * [Link]
else:
[Link] = Vector2(0,0)
# shooting
self.time_since_shot += dt
if self.time_since_shot >= self.fire_rate and dist < 520:
self.time_since_shot = 0
dir = to_player.normalize() if dist>0 else Vector2(1,0)
vel = dir * BOT_BULLET_SPEED
return Bullet([Link] + dir*22, vel, self, damage=20)
else:
# wander
self.time_since_shot += dt
if [Link]() < 0.01:
self.wander_dir = Vector2([Link](-1,1), [Link](-1,1))
if self.wander_dir.length_squared()>0:
self.wander_dir = self.wander_dir.normalize()
[Link] = self.wander_dir * [Link] * 0.6
[Link] += [Link] * dt
# stay inside map
[Link].x = clamp([Link].x, 0, MAP_W)
[Link].y = clamp([Link].y, 0, MAP_H)
return None
def draw(self, surf, cam):
p = world_to_screen([Link], cam)
[Link](surf, [Link], (int(p.x), int(p.y)), [Link])
self.draw_healthbar(surf, cam)
# --- Map and world ---
HOUSES = []
VEHICLES = []
def generate_map():
global HOUSES, VEHICLES
HOUSES = []
VEHICLES = []
# create houses as rectangles randomly positioned
for i in range(30):
w = [Link](90,220)
h = [Link](80,180)
x = [Link](50, MAP_W - 50 - w)
y = [Link](50, MAP_H - 50 - h)
[Link]([Link](x,y,w,h))
# vehicles as small rectangles
for i in range(40):
w = [Link](30,70)
h = [Link](20,40)
x = [Link](20, MAP_W - 20 - w)
y = [Link](20, MAP_H - 20 - h)
[Link]([Link](x,y,w,h))
# --- Camera ---
def world_to_screen(pos, cam):
return Vector2(pos.x - cam.x + SCREEN_W/2, pos.y - cam.y + SCREEN_H/2)
def screen_to_world(pos, cam):
return Vector2(pos[0] + cam.x - SCREEN_W/2, pos[1] + cam.y - SCREEN_H/2)
# --- Game state ---
class GameState:
def __init__(self):
self.in_lobby = True
[Link] = Player(Vector2(MAP_W/2, MAP_H/2))
[Link] = []
[Link] = []
self.spawn_points = []
self.coins_display = 0
def start_match(self):
# reset things
self.in_lobby = False
generate_map()
[Link] = Player(Vector2([Link](100, MAP_W-100), [Link](100, MAP_H-100)))
[Link] = []
[Link] = []
# create spawn points away from player
self.spawn_points = []
for i in range(NUM_BOTS+20):
x = [Link](50, MAP_W-50)
y = [Link](50, MAP_H-50)
if Vector2(x,y).distance_to([Link]) > 300:
self.spawn_points.append(Vector2(x,y))
[Link](self.spawn_points)
# spawn NUM_BOTS bots
for i in range(NUM_BOTS):
if i < len(self.spawn_points):
pos = self.spawn_points[i]
else:
pos = Vector2([Link](50,MAP_W-50), [Link](50,MAP_H-50))
b = Bot(pos)
[Link](b)
def end_round_to_lobby(self, player_won=False):
if player_won:
[Link] += WIN_BONUS
# tiny delay handled by caller
self.in_lobby = True
def update(self, dt, keys, mouse_world, mouse_pressed):
if self.in_lobby:
return
if not [Link]:
# return to lobby
self.end_round_to_lobby(player_won=False)
return
# update player
[Link](dt, keys, mouse_world)
# shooting
if mouse_pressed[0]:
b = [Link](mouse_world)
if b:
[Link](b)
# update bots
for bot in [Link]:
if not [Link]: continue
newb = [Link](dt, [Link])
if newb:
[Link](newb)
# update bullets
to_remove = []
for bullet in [Link]:
alive = [Link](dt)
if not alive:
to_remove.append(bullet)
continue
# collision against bots and player
if [Link] == 'player':
for bot in [Link]:
if not [Link]: continue
if [Link].distance_to([Link]) < [Link]+6:
bot.take_damage([Link], attacker=[Link])
to_remove.append(bullet)
if not [Link]:
[Link] += KILL_COINS
[Link] += 1
break
else:
# owner is Bot instance
if [Link].distance_to([Link]) < [Link]+6 and [Link]:
[Link].take_damage([Link], attacker=[Link])
to_remove.append(bullet)
if not [Link]:
# player eliminated
# award coins to killer bot? specs ask only player coins so skip
pass
for r in to_remove:
if r in [Link]:
[Link](r)
# check win condition: is the player last alive among actors?
others_alive = sum(1 for b in [Link] if [Link])
if others_alive == 0:
# player won
self.end_round_to_lobby(player_won=True)
def draw_world(self, surf, cam, mouse_world):
# draw ground
[Link]((50,130,50))
# Houses (as rectangles)
for rect in HOUSES:
r = [Link](rect.x - cam.x + SCREEN_W/2, rect.y - cam.y + SCREEN_H/2, [Link], [Link])
[Link](surf, (170,120,100), r)
[Link](surf, (100,60,40), r, 3)
# Vehicles
for rect in VEHICLES:
r = [Link](rect.x - cam.x + SCREEN_W/2, rect.y - cam.y + SCREEN_H/2, [Link], [Link])
[Link](surf, (50,50,120), r)
[Link](surf, (10,10,40), r, 2)
# bots
for bot in [Link]:
if [Link]:
[Link](surf, cam)
# bullets
for bullet in [Link]:
[Link](surf, cam)
# player
if [Link]:
[Link](surf, cam, mouse_world)
def draw_hud(self, surf):
# top-left: health, coins, kills
health_surf = [Link](f'Health: {int([Link])}/{[Link].max_health}', True, WHITE)
coins_surf = [Link](f'Coins: {[Link]}', True, YELLOW)
kills_surf = [Link](f'Kills: {[Link]}', True, WHITE)
[Link](health_surf, (12,12))
[Link](coins_surf, (12,40))
[Link](kills_surf, (12,68))
# --- UI / Lobby ---
def draw_lobby(surf):
[Link]((20,30,50))
title = [Link]('Lobby - 2D Shooter Prototype', True, WHITE)
info = [Link]('Click START to spawn player + 29 bots. Each kill = 10 coins. Last player standing =
+100 coins.', True, WHITE)
[Link](title, (SCREEN_W//2 - title.get_width()//2, 120))
[Link](info, (SCREEN_W//2 - info.get_width()//2, 200))
# start button
btn_rect = [Link](SCREEN_W//2 - 120, 300, 240, 70)
[Link](surf, (80,200,100), btn_rect)
[Link](surf, WHITE, btn_rect, 3)
txt = [Link]('START', True, BLACK)
[Link](txt, (btn_rect.x + btn_rect.width//2 - txt.get_width()//2, btn_rect.y + btn_rect.height//2 -
txt.get_height()//2))
return btn_rect
# --- Main Loop ---
game = GameState()
def main():
running = True
respawn_timer = 0.0
while running:
dt = [Link](FPS) / 1000.0
for event in [Link]():
if [Link] == [Link]:
running = False
if [Link] == [Link]:
if [Link] == pygame.K_ESCAPE:
running = False
keys = [Link].get_pressed()
mouse_pressed = [Link].get_pressed()
mouse_screen = [Link].get_pos()
if game.in_lobby:
btn = draw_lobby(screen)
[Link]()
# handle clicks
for evt in [Link]():
if [Link] == [Link]:
running = False
if [Link] == [Link] and [Link] == 1:
if [Link]([Link]):
game.start_match()
continue
# camera centers on player
cam = Vector2([Link].x, [Link].y)
mouse_world = screen_to_world(mouse_screen, cam)
# update game
[Link](dt, keys, mouse_world, mouse_pressed)
# draw world
game.draw_world(screen, cam, mouse_world)
# HUD
game.draw_hud(screen)
# Crosshair
[Link](screen, WHITE, mouse_screen, 6, 2)
[Link]()
[Link]()
if __name__ == '__main__':
main()
MY SQL CATALOUGE
-- Database creation
CREATE DATABASE IF NOT EXISTS GameDB;
USE GameDB;
-- Players Table
CREATE TABLE Players (
player_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Characters Table
CREATE TABLE Characters (
character_id INT AUTO_INCREMENT PRIMARY KEY,
player_id INT,
character_name VARCHAR(50),
level INT DEFAULT 1,
health INT DEFAULT 100,
experience INT DEFAULT 0,
FOREIGN KEY (player_id) REFERENCES Players(player_id)
);
-- Inventory Table
CREATE TABLE Inventory (
inventory_id INT AUTO_INCREMENT PRIMARY KEY,
player_id INT,
item_name VARCHAR(50),
quantity INT DEFAULT 1,
FOREIGN KEY (player_id) REFERENCES Players(player_id)
);
-- Matches Table
CREATE TABLE Matches (
match_id INT AUTO_INCREMENT PRIMARY KEY,
player_id INT,
kills INT DEFAULT 0,
deaths INT DEFAULT 0,
score INT DEFAULT 0,
match_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (player_id) REFERENCES Players(player_id)
);
-- Shop Table
CREATE TABLE Shop (
item_id INT AUTO_INCREMENT PRIMARY KEY,
item_name VARCHAR(50),
item_type VARCHAR(50),
price INT
);
BIBLIGRAPHY
1. COMPUTER SCIENCE WITH PYTHON [ CLASS
11 ].
2. COMPUTER SCIENCE WITH PYTHON CLASS [
12 ]