Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
Project Zavi
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mihkelhain
Project Zavi
Commits
a8eef080
Unverified
Commit
a8eef080
authored
4 months ago
by
Mihkel Hain
Browse files
Options
Downloads
Patches
Plain Diff
Firing add ig lk im just chill guy
parent
f0460ff7
Branches
towerFire
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
.main.py.kate-swp
+0
-0
0 additions, 0 deletions
.main.py.kate-swp
enemy.py
+47
-9
47 additions, 9 deletions
enemy.py
main.py
+19
-31
19 additions, 31 deletions
main.py
turret.py
+32
-14
32 additions, 14 deletions
turret.py
with
98 additions
and
54 deletions
.main.py.kate-swp
0 → 100644
+
0
−
0
View file @
a8eef080
File added
This diff is collapsed.
Click to expand it.
enemy.py
+
47
−
9
View file @
a8eef080
"""
This module contains the Enemy class.
"""
import
pygame
as
pg
class
Enemy
:
"""
Class for the enemy object.
"""
def
__init__
(
self
,
hp
:
float
,
speed
:
float
,
damage
:
float
,
texture_path
:
str
):
"""
Initializes the enemy object.
"""
self
.
hp
=
hp
self
.
max_hp
=
hp
self
.
speed
=
speed
self
.
damage
=
damage
self
.
texture_path
=
texture_path
...
...
@@ -14,13 +12,27 @@ class Enemy:
self
.
path_position
=
0
self
.
screen_position
=
(
0
,
0
)
self
.
full_path_time
=
20
self
.
alive
=
True
def
take_damage
(
self
,
amount
:
float
):
"""
Reduces the enemy
'
s HP by the given damage amount.
Parameters:
amount:
The amount of damage to apply to the enemy.
"""
self
.
hp
-=
amount
if
self
.
hp
<=
0
:
self
.
hp
=
0
self
.
alive
=
False
# Mark enemy as dead
def
calculate_current_path_segment
(
self
,
path
:
tuple
[
tuple
[
int
,
int
]])
->
int
:
"""
Returns the index of current path segment and the distance along the path segment.
Returns the index of
the
current path segment and the distance along the path segment.
Parameters:
waypoints
:
path
:
The waypoints of the path.
"""
# First find the length of each path segment
...
...
@@ -37,8 +49,9 @@ class Enemy:
return
i
,
segment_position
current_path_length
+=
path_lengths
[
i
]
if
current_path_length
>=
full_path_length
:
# Return the end of the last path segment if the path_position more than 1
# Return the end of the last path segment if the path_position
is
more than 1
return
len
(
path
)
-
2
,
1
def
move_along_path
(
self
,
dt
:
float
,
path
:
tuple
[
tuple
[
int
,
int
]]):
"""
Moves the enemy along the path.
...
...
@@ -55,23 +68,48 @@ class Enemy:
path
[
path_segment
][
0
]
+
(
path
[
path_segment
+
1
][
0
]
-
path
[
path_segment
][
0
])
*
segment_position
,
path
[
path_segment
][
1
]
+
(
path
[
path_segment
+
1
][
1
]
-
path
[
path_segment
][
1
])
*
segment_position
)
def
draw
(
self
,
surface
):
"""
Draws the enemy to the passed surface.
Draws the enemy
and its health bar
to the passed surface.
Parameters:
surface:
The surface to draw the enemy to.
"""
# Draw the enemy sprite
self
.
texture_rect
=
self
.
texture
.
get_rect
()
self
.
texture_rect
.
center
=
self
.
screen_position
surface
.
blit
(
self
.
texture
,
self
.
texture_rect
)
# Health bar bit
if
self
.
hp
>
0
:
bar_width
=
self
.
texture_rect
.
width
bar_height
=
6
health_ratio
=
self
.
hp
/
self
.
max_hp
health_bar_rect
=
pg
.
Rect
(
self
.
texture_rect
.
left
,
self
.
texture_rect
.
top
-
bar_height
-
4
,
bar_width
*
health_ratio
,
bar_height
)
background_bar_rect
=
pg
.
Rect
(
self
.
texture_rect
.
left
,
self
.
texture_rect
.
top
-
bar_height
-
4
,
bar_width
,
bar_height
)
# Background bar (gray)
pg
.
draw
.
rect
(
surface
,
(
100
,
100
,
100
),
background_bar_rect
)
# Foreground bar (green)
pg
.
draw
.
rect
(
surface
,
(
0
,
200
,
0
),
health_bar_rect
)
# TODO: Rotate the sprite to face the direction of movement.
#Hope you dont mind me slotting this here
def
kill
(
self
):
self
.
hp
=
0
self
.
alive
=
False
class
Zombie
(
Enemy
):
"""
Class for the zombie object.
"""
def
__init__
(
self
):
"""
Initializes the zombie object.
"""
super
().
__init__
(
100
,
1
,
10
,
'
assets/images/zombie/skeleton-idle_0.png
'
)
super
().
__init__
(
100
,
1
,
10
,
'
assets/images/zombie/skeleton-idle_0.png
'
)
This diff is collapsed.
Click to expand it.
main.py
+
19
−
31
View file @
a8eef080
...
...
@@ -20,6 +20,7 @@ from world import World
from
turret
import
Turret
from
gui
import
GUI
def
main
():
# World object creation
world
=
World
()
...
...
@@ -32,17 +33,14 @@ def main():
dt
=
1
/
1000
time_now
=
time
.
time
()
# MOUSE TESTING
mouseSquare
=
pg
.
Rect
(
0
,
0
,
100
,
100
)
#Button implemnentation test :)
# Button implementation
button_width
,
button_height
=
400
,
60
button_x
=
world
.
window_resolution
[
0
]
-
button_width
-
100
# right
button_y
=
world
.
window_resolution
[
1
]
-
button_height
-
20
# Bottom
buy_button
=
pg
.
Rect
(
button_x
,
button_y
,
button_width
,
button_height
)
#Nec
c
essary boolean
dont question >:(
#
Necessary boolean
can_place_turrets
=
False
# Groups
...
...
@@ -57,9 +55,6 @@ def main():
dt
=
time
.
time
()
-
time_now
time_now
=
time
.
time
()
#Turret delta time
turret_group
.
update
(
world
.
enemies
,
dt
)
# Input handling
for
event
in
pg
.
event
.
get
():
if
event
.
type
==
pg
.
QUIT
:
...
...
@@ -68,22 +63,11 @@ def main():
if
event
.
type
==
pg
.
KEYDOWN
:
if
event
.
key
==
pg
.
K_ESCAPE
:
running
=
False
# Choose the tower to place with the number keys
if
event
.
key
==
pg
.
K_1
:
if
active_tower
!=
2
:
active_tower
=
2
else
:
active_tower
=
0
if
event
.
key
==
pg
.
K_2
:
if
active_tower
!=
2
:
active_tower
=
2
else
:
active_tower
=
0
# Start the round with the space key
if
event
.
key
==
pg
.
K_SPACE
and
not
world
.
round_active
:
world
.
request_to_start_round
=
True
#Turret
P
lacement logic
central 101
#
Turret
p
lacement logic
if
event
.
type
==
pg
.
MOUSEBUTTONDOWN
and
event
.
button
==
1
:
mouse_pos
=
pg
.
mouse
.
get_pos
()
# Buy button pressing check
...
...
@@ -93,8 +77,6 @@ def main():
elif
can_place_turrets
:
Turret
.
spawn_turret
(
cursor_turret
,
mouse_pos
,
turret_group
)
# Game state updates
if
world
.
round_active
:
# Spawn enemies at the correct time
...
...
@@ -105,9 +87,11 @@ def main():
break
for
enemy
in
world
.
enemies
:
enemy
.
move_along_path
(
dt
,
world
.
waypoints
)
# Dead ennemy removal
world
.
enemies
=
[
enemy
for
enemy
in
world
.
enemies
if
enemy
.
alive
]
#Turret turn update
turret_group
.
update
(
world
.
enemies
)
# Update turrets (hitscan mechanism)
turret_group
.
update
(
world
.
enemies
)
if
world
.
request_to_start_round
:
world
.
current_round
+=
1
...
...
@@ -118,18 +102,22 @@ def main():
# Drawing
world
.
draw
()
# Box for collision tower purposes
# Highlight turret placement area
if
can_place_turrets
:
mouseSquare
.
center
=
pg
.
mouse
.
get_pos
()
pg
.
draw
.
rect
(
world
.
window
,
(
255
,
0
,
0
),
mouseSquare
,
6
,
1
)
# Turret draw
mouse_pos
=
pg
.
mouse
.
get_pos
()
placement_indicator
=
pg
.
Rect
(
0
,
0
,
100
,
100
)
placement_indicator
.
center
=
mouse_pos
pg
.
draw
.
rect
(
world
.
window
,
(
255
,
0
,
0
),
placement_indicator
,
6
,
1
)
# Draw turrets
turret_group
.
draw
(
world
.
window
)
#Button
button_color
=
(
0
,
200
,
0
)
if
can_place_turrets
else
(
200
,
0
,
0
)
#I think feedback is good if the button is active or not
# Buy button
button_color
=
(
0
,
200
,
0
)
if
can_place_turrets
else
(
200
,
0
,
0
)
pg
.
draw
.
rect
(
world
.
window
,
button_color
,
buy_button
)
gui
.
draw_text
(
world
.
window
,
"
BUY TURRET
"
,
(
button_x
+
button_width
/
2
,
button_y
+
button_height
/
2
),
'
center
'
)
# Draw the round number
gui
.
draw_text
(
world
.
window
,
f
"
ROUND:
{
world
.
current_round
}
"
,
(
world
.
window_resolution
[
0
]
-
margin
,
margin
),
'
topright
'
)
...
...
This diff is collapsed.
Click to expand it.
turret.py
+
32
−
14
View file @
a8eef080
import
pygame
as
pg
import
math
#need to make init actually take numbers instead of preset
class
Turret
(
pg
.
sprite
.
Sprite
):
def
__init__
(
self
,
image
,
pos
):
def
__init__
(
self
,
image
,
pos
,
range_radius
=
200
,
damage
=
10
,
fire_rate
=
0.5
):
super
().
__init__
()
self
.
original_image
=
image
self
.
image
=
image
self
.
rect
=
self
.
image
.
get_rect
()
self
.
rect
.
center
=
pos
self
.
target_angle
=
0
self
.
range_radius
=
range_radius
self
.
damage
=
damage
self
.
fire_rate
=
fire_rate
self
.
last_shot_time
=
0
@staticmethod
def
spawn_turret
(
image
,
mouse_pos
,
turret_group
):
#Spawn function that actually doesnt allow collision wow :) (I spent 4 hours on this :(.)
collision
=
False
if
mouse_pos
[
0
]
<
1920
and
mouse_pos
[
1
]
<
1080
:
temp_turret
=
Turret
(
image
,
mouse_pos
)
...
...
@@ -22,28 +25,43 @@ class Turret(pg.sprite.Sprite):
turret_group
.
add
(
temp_turret
)
def
update
(
self
,
enemies
):
#Basically finds the nearest enemy :)
if
enemies
:
# Find the closest enemy
nearest_enemy
=
min
(
enemies
,
key
=
lambda
e
:
self
.
distance_to_enemy
(
e
))
self
.
target_angle
=
self
.
calculate_angle
(
nearest_enemy
)
self
.
rotate_turret
()
nearest_enemy
=
self
.
find_nearest_enemy
(
enemies
)
if
nearest_enemy
and
self
.
is_within_range
(
nearest_enemy
):
# Rotate towards the enemy
self
.
target_angle
=
self
.
calculate_angle
(
nearest_enemy
)
self
.
rotate_turret
()
# Check fire rate and shoot
current_time
=
pg
.
time
.
get_ticks
()
/
1000
# Convert ms to seconds
if
current_time
-
self
.
last_shot_time
>=
self
.
fire_rate
:
self
.
shoot
(
nearest_enemy
)
self
.
last_shot_time
=
current_time
def
find_nearest_enemy
(
self
,
enemies
):
return
min
(
enemies
,
key
=
lambda
e
:
self
.
distance_to_enemy
(
e
),
default
=
None
)
def
is_within_range
(
self
,
enemy
):
return
self
.
distance_to_enemy
(
enemy
)
<=
self
.
range_radius
#I hate math (feeds towards update)
def
distance_to_enemy
(
self
,
enemy
):
return
math
.
hypot
(
enemy
.
screen_position
[
0
]
-
self
.
rect
.
centerx
,
enemy
.
screen_position
[
1
]
-
self
.
rect
.
centery
)
#
Angel towards enemy (Feeds towards update)
#
I hate meth
def
calculate_angle
(
self
,
enemy
):
dx
=
enemy
.
screen_position
[
0
]
-
self
.
rect
.
centerx
dy
=
enemy
.
screen_position
[
1
]
-
self
.
rect
.
centery
angle
=
math
.
degrees
(
math
.
atan2
(
-
dy
,
dx
))
# Negative Y-axis correction
return
angle
-
90
# Adjust for the turret facing upward
angle
=
math
.
degrees
(
math
.
atan2
(
-
dy
,
dx
))
return
angle
-
90
#Whats written on the tin (Feesd towards update)
def
rotate_turret
(
self
):
"""
Rotate the turret image based on the calculated angle.
"""
self
.
image
=
pg
.
transform
.
rotate
(
self
.
original_image
,
self
.
target_angle
)
self
.
rect
=
self
.
image
.
get_rect
(
center
=
self
.
rect
.
center
)
def
shoot
(
self
,
enemy
):
#Print is for console, purposes, might disable later???
print
(
f
"
Turret at
{
self
.
rect
.
center
}
hits enemy at
{
enemy
.
screen_position
}
for
{
self
.
damage
}
damage!
"
)
enemy
.
take_damage
(
self
.
damage
)
# Use the take_damage method
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment