-
Notifications
You must be signed in to change notification settings - Fork 0
/
flappy_bird.py
161 lines (131 loc) · 4.84 KB
/
flappy_bird.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import pygame
import random
import numpy as np
from dqn_agent import DQNAgent
from config import Config
import torch
import csv
from datetime import datetime, timedelta
from image_preprocessor import preprocess_images
# Initialize Pygame
pygame.init()
# Game Constants
WIDTH, HEIGHT = 400, 600
# Preprocess images
preprocess_images(WIDTH, HEIGHT)
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
CLOCK = pygame.time.Clock()
FONT = pygame.font.SysFont('comicsans', 30)
# Load images (now they're already scaled)
BIRD_IMG = pygame.image.load('assets/bird.png')
PIPE_IMG = pygame.image.load('assets/pipe.png')
BG_IMG = pygame.image.load('assets/background.png')
# Player settings
PLAYER_WIDTH, PLAYER_HEIGHT = 50, 50
PLAYER_X, PLAYER_Y = 100, HEIGHT // 2
GRAVITY = 0.5
JUMP_STRENGTH = -10
# Obstacle settings
OBSTACLE_WIDTH = 70
OBSTACLE_GAP = 200
# DQN Agent Initialization
config = Config()
agent = DQNAgent(config)
# Add these global variables
start_time = None
csv_file = 'game_logs.csv'
# Game Functions
def draw_player(x, y):
SCREEN.blit(BIRD_IMG, (x, y))
def draw_obstacle(obstacles):
for obs in obstacles:
# Draw top pipe
top_pipe = pygame.transform.flip(PIPE_IMG, False, True)
SCREEN.blit(top_pipe, (obs[0], obs[1] - OBSTACLE_GAP // 2 - PIPE_IMG.get_height()))
# Draw bottom pipe
SCREEN.blit(PIPE_IMG, (obs[0], obs[1] + OBSTACLE_GAP // 2))
def reset_game():
global PLAYER_Y, player_velocity, obstacles, score, start_time
PLAYER_Y = HEIGHT // 2
player_velocity = 0
obstacles = [[WIDTH, random.randint(OBSTACLE_GAP, HEIGHT - OBSTACLE_GAP), HEIGHT]]
score = 0
if start_time is None:
start_time = datetime.now()
return np.array([PLAYER_Y, player_velocity, WIDTH, obstacles[0][1]])
def check_collision(player_y, obstacles):
player_rect = pygame.Rect(PLAYER_X, player_y, PLAYER_WIDTH, PLAYER_HEIGHT)
for obs in obstacles:
top_pipe = pygame.Rect(obs[0], 0, OBSTACLE_WIDTH, obs[1] - OBSTACLE_GAP // 2)
bottom_pipe = pygame.Rect(obs[0], obs[1] + OBSTACLE_GAP // 2, OBSTACLE_WIDTH, HEIGHT - (obs[1] + OBSTACLE_GAP // 2))
if player_rect.colliderect(top_pipe) or player_rect.colliderect(bottom_pipe):
return True
return False
def game_step(action):
global PLAYER_Y, player_velocity, obstacles, score
player_velocity += GRAVITY
if action == 1:
player_velocity = JUMP_STRENGTH
PLAYER_Y += player_velocity
# Move and generate obstacles
for obs in obstacles:
obs[0] -= config.obstacle_speed
if obstacles[-1][0] < WIDTH - OBSTACLE_GAP:
obstacles.append([WIDTH, random.randint(OBSTACLE_GAP, HEIGHT - OBSTACLE_GAP), HEIGHT])
if obstacles[0][0] < -OBSTACLE_WIDTH:
obstacles.pop(0)
# Update score
score += 1
state = np.array([PLAYER_Y, player_velocity, obstacles[0][0], obstacles[0][1]])
# Check for collisions with pipes or screen boundaries
if check_collision(PLAYER_Y, obstacles) or PLAYER_Y <= 0 or PLAYER_Y >= HEIGHT - PLAYER_HEIGHT:
reward = config.negative_reward
done = True
else:
reward = config.positive_reward
done = False
return state, reward, done
def log_score(score, start_time, end_time):
duration = end_time - start_time
with open(csv_file, 'a', newline='') as file:
writer = csv.writer(file)
writer.writerow([score, start_time.isoformat(), end_time.isoformat(), str(duration)])
def main():
global PLAYER_Y, player_velocity, score, start_time
score = 0
state = reset_game()
while True:
SCREEN.blit(BG_IMG, (0, 0))
CLOCK.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
action = agent.act(state)
next_state, reward, done = game_step(action)
agent.remember(state, action, reward, next_state, done)
agent.replay() # Train on previous experiences
state = next_state
draw_player(PLAYER_X, PLAYER_Y)
draw_obstacle(obstacles)
# Display score
score_text = FONT.render(f"Score: {score}", True, (255, 255, 255))
SCREEN.blit(score_text, (10, 10))
if done or score >= 7848:
end_time = datetime.now()
print(f"Game Over! Score: {score}")
log_score(score, start_time, end_time)
if score >= 7848:
print(f"Target score reached! Time taken: {end_time - start_time}")
return
state = reset_game()
agent.update_target_model()
pygame.display.update()
# Optimize rewards
if score % 100 == 0:
config.optimize_rewards()
if __name__ == "__main__":
with open(csv_file, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['Score', 'Start Time', 'End Time', 'Duration'])
main()
pygame.quit()