Skip to content

Commit 2d69392

Browse files
committed
Adding episode 4 Level Loading
1 parent 44a7bdb commit 2d69392

12 files changed

+1057
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
2+
<PropertyGroup>
3+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4+
<SchemaVersion>2.0</SchemaVersion>
5+
<ProjectGuid>d963f6b8-800b-494d-9138-d57bb4516bc2</ProjectGuid>
6+
<ProjectHome>.</ProjectHome>
7+
<StartupFile>_04_LevelLoading.py</StartupFile>
8+
<SearchPath>
9+
</SearchPath>
10+
<WorkingDirectory>.</WorkingDirectory>
11+
<OutputPath>.</OutputPath>
12+
<Name>04_LevelLoading</Name>
13+
<RootNamespace>04_LevelLoading</RootNamespace>
14+
</PropertyGroup>
15+
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
16+
<DebugSymbols>true</DebugSymbols>
17+
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
18+
</PropertyGroup>
19+
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
20+
<DebugSymbols>true</DebugSymbols>
21+
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
22+
</PropertyGroup>
23+
<ItemGroup>
24+
<Compile Include="ClassBackground.py" />
25+
<Compile Include="ClassBee.py" />
26+
<Compile Include="ClassHero.py" />
27+
<Compile Include="ClassLevel.py" />
28+
<Compile Include="ClassSpriteSheet.py" />
29+
<Compile Include="ClassTile.py">
30+
<SubType>Code</SubType>
31+
</Compile>
32+
<Compile Include="Config.py" />
33+
<Compile Include="_04_LevelLoading.py" />
34+
</ItemGroup>
35+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
36+
<!-- Uncomment the CoreCompile target to enable the Build command in
37+
Visual Studio and specify your pre- and post-build commands in
38+
the BeforeBuild and AfterBuild targets below. -->
39+
<!--<Target Name="CoreCompile" />-->
40+
<Target Name="BeforeBuild">
41+
</Target>
42+
<Target Name="AfterBuild">
43+
</Target>
44+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pygame
2+
from Config import *
3+
4+
5+
class Background():
6+
7+
def __init__(self):
8+
# Create the sky image
9+
self.skyImage = pygame.image.load(SPRITESHEET_PATH + "Background/Background.png").convert()
10+
self.skyImage = pygame.transform.scale(self.skyImage, (WINDOW_WIDTH, WINDOW_HEIGHT))
11+
12+
13+
def draw(self, displaySurface):
14+
# Draw sky image
15+
displaySurface.blit(self.skyImage, (0, 0))
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import pygame
2+
from Config import *
3+
from ClassSpriteSheet import SpriteSheet
4+
5+
6+
beeSprites = [
7+
(16, 0, 48, 48),
8+
(80, 0, 48, 48),
9+
(144, 0, 48, 48),
10+
(208, 0, 48, 48)
11+
]
12+
13+
14+
class Bee(pygame.sprite.Sprite):
15+
16+
def __init__(self, position, moveRight):
17+
super().__init__()
18+
19+
# Load spritesheets
20+
self.flySpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Mob/Small bee/Fly/Fly-Sheet.png", beeSprites)
21+
self.hitSpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Mob/Small bee/Hit/Hit-Sheet.png", beeSprites)
22+
self.attackSpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Mob/Small bee/Attack/Attack-Sheet.png", beeSprites)
23+
24+
self.image = self.flySpriteSheet.getSprites(moveRight)[0]
25+
self.rect = self.image.get_rect(bottomleft = position)
26+
self.movingRight = moveRight
27+
self.yDir = 0
28+
self.animationIndex = 0
29+
self.currentState = 'FLY'
30+
31+
32+
def update(self, level):
33+
# Update position
34+
if self.movingRight == False:
35+
self.rect.x -= SPEED_BEE
36+
else:
37+
self.rect.x += SPEED_BEE
38+
39+
# When flying outside the window, just turn around
40+
if self.rect.right < 0:
41+
self.movingRight = True
42+
if self.rect.left > WINDOW_WIDTH:
43+
self.movingRight = False
44+
45+
if self.currentState == 'DYING':
46+
self.yDir += GRAVITY
47+
self.rect.y += self.yDir
48+
# Destroy sprite when bee has fallen outside the window
49+
if self.rect.top > WINDOW_HEIGHT:
50+
self.kill()
51+
52+
# trigger attack
53+
heroRect = level.hero.sprite.rect
54+
heroX = heroRect.centerx
55+
if self.currentState == 'FLY':
56+
if heroRect.top < self.rect.bottom <= heroRect.bottom:
57+
if self.movingRight == True:
58+
if self.rect.left < heroX and self.rect.right > heroX - 50:
59+
self.currentState = 'ATTACK'
60+
self.animationIndex = 0
61+
else:
62+
if self.rect.right > heroX and self.rect.left < heroX + 50:
63+
self.currentState = 'ATTACK'
64+
self.animationIndex = 0
65+
elif self.currentState == 'ATTACK':
66+
if self.movingRight == True:
67+
if self.rect.left >= heroX or self.rect.right < heroX - 50:
68+
self.currentState = 'FLY'
69+
self.animationIndex = 0
70+
else:
71+
if self.rect.right <= heroX or self.rect.left > heroX + 50:
72+
self.currentState = 'FLY'
73+
self.animationIndex = 0
74+
75+
# Select animation for current action
76+
self.selectAnimation()
77+
78+
# Animate sprite
79+
self.animationIndex += self.animationSpeed
80+
if self.animationIndex >= len(self.currentAnimation):
81+
if self.currentState == 'ATTACK' or self.currentState == 'DYING':
82+
self.animationIndex = len(self.currentAnimation) - 1
83+
else:
84+
self.currentState = 'FLY'
85+
self.animationIndex = 0
86+
87+
self.image = self.currentAnimation[int(self.animationIndex)]
88+
89+
90+
def selectAnimation(self):
91+
self.animationSpeed = ANIMSPEED_BEE
92+
if self.currentState == 'FLY':
93+
self.currentAnimation = self.flySpriteSheet.getSprites(flipped = self.movingRight)
94+
elif self.currentState == 'ATTACK':
95+
self.animationSpeed = ANIMSPEED_BEE_ATTACK
96+
self.currentAnimation = self.attackSpriteSheet.getSprites(flipped = self.movingRight)
97+
else:
98+
self.currentAnimation = self.hitSpriteSheet.getSprites(flipped = self.movingRight)
99+
100+
101+
def die(self):
102+
if self.currentState != 'DYING':
103+
self.animationIndex = 0
104+
self.currentState = 'DYING'
+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import pygame
2+
from Config import *
3+
from ClassSpriteSheet import SpriteSheet
4+
5+
6+
runSprites = [
7+
(24, 16, 40, 52),
8+
(104, 16, 40, 52),
9+
(184, 16, 40, 52),
10+
(264, 16, 40, 52),
11+
(344, 16, 40, 52),
12+
(424, 16, 40, 52),
13+
(504, 16, 40, 52),
14+
(584, 16, 40, 52)
15+
]
16+
17+
idleSprites = [
18+
(12, 12, 44, 52),
19+
(76, 12, 44, 52),
20+
(140, 12, 44, 52),
21+
(204, 12, 44, 52)
22+
]
23+
24+
attackSprites = [
25+
(4, 0, 92, 80),
26+
(100, 0, 92, 80),
27+
(196, 0, 92, 80),
28+
(294, 0, 92, 80),
29+
(388, 0, 92, 80),
30+
(484, 0, 92, 80),
31+
(580, 0, 92, 80),
32+
(676, 0, 92, 80)
33+
]
34+
35+
deathSprites = [
36+
(0, 0, 64, 56),
37+
(80, 0, 64, 56),
38+
(160, 0, 64, 56),
39+
(240, 0, 64, 56),
40+
(320, 0, 64, 56),
41+
(400, 0, 64, 56),
42+
(480, 0, 64, 56),
43+
(560, 0, 64, 56)
44+
]
45+
46+
47+
48+
class Hero(pygame.sprite.Sprite):
49+
50+
def __init__(self, position, faceRight):
51+
super().__init__()
52+
53+
# Load spritesheets
54+
idleSpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Character/Idle/Idle-Sheet.png", idleSprites)
55+
runSpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Character/Run/Run-Sheet.png", runSprites)
56+
attackSpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Character/Attack-01/Attack-01-Sheet.png", attackSprites)
57+
deathSpriteSheet = SpriteSheet(SPRITESHEET_PATH + "Character/Dead/Dead-Sheet.png", deathSprites)
58+
59+
self.spriteSheets = {
60+
'IDLE' : idleSpriteSheet,
61+
'RUN' : runSpriteSheet,
62+
'ATTACK' : attackSpriteSheet,
63+
'DIE' : deathSpriteSheet
64+
}
65+
66+
self.animationIndex = 0
67+
self.facingRight = faceRight
68+
self.currentState = 'IDLE'
69+
self.xDir = 0
70+
self.speed = SPEED_HERO
71+
self.xPos = position[0]
72+
self.yPos = position[1]
73+
74+
75+
def update(self, level):
76+
self.previousState = self.currentState
77+
self.xDir = 0
78+
79+
# get key status
80+
if self.currentState != 'ATTACK' and self.currentState != 'DIE':
81+
keys = pygame.key.get_pressed()
82+
if keys[pygame.K_SPACE]:
83+
self.currentState = 'ATTACK'
84+
elif keys[pygame.K_LEFT]:
85+
self.xDir = -1
86+
self.facingRight = False
87+
self.currentState = 'RUN'
88+
elif keys[pygame.K_RIGHT]:
89+
self.xDir = 1
90+
self.facingRight = True
91+
self.currentState = 'RUN'
92+
else:
93+
self.currentState = 'IDLE'
94+
95+
# Select animation for current player action (idle, run, jump, fall, etc.)
96+
self.selectAnimation()
97+
98+
# Start from beginning of a new animation
99+
if self.previousState != self.currentState:
100+
self.animationIndex = 0
101+
102+
# Select the image
103+
self.image = self.currentAnimation[int(self.animationIndex)]
104+
105+
# Select a rect size depending on the current animation
106+
# (xPos, yPos) = bottom-center position of the sprite
107+
if self.currentState == 'IDLE':
108+
self.rect = pygame.Rect(self.xPos - 22, self.yPos - 52, 44, 52)
109+
elif self.currentState == 'RUN':
110+
self.rect = pygame.Rect(self.xPos - 20, self.yPos - 48, 40, 48)
111+
elif self.currentState == 'ATTACK':
112+
self.rect = pygame.Rect(self.xPos - 44, self.yPos - 64, 88, 64)
113+
elif self.currentState == 'DIE':
114+
self.rect = pygame.Rect(self.xPos - 32, self.yPos - 48, 64, 48)
115+
116+
# Play animation until end of current animation is reached
117+
self.animationIndex += self.animationSpeed
118+
if self.animationIndex >= len(self.currentAnimation):
119+
if self.currentState == 'DIE':
120+
self.animationIndex = len(self.currentAnimation) - 1
121+
else:
122+
self.animationIndex = 0
123+
self.currentState = 'IDLE'
124+
125+
self.moveHorizontal(level)
126+
127+
# Handle collisions with enemies
128+
self.checkEnemyCollisions(level.bees)
129+
130+
131+
def selectAnimation(self):
132+
self.animationSpeed = ANIMSPEED_HERO_DEFAULT
133+
if self.currentState == 'IDLE':
134+
self.animationSpeed = ANIMSPEED_HERO_IDLE
135+
136+
spriteSheet = self.spriteSheets[self.currentState]
137+
self.currentAnimation = spriteSheet.getSprites(flipped = not self.facingRight)
138+
139+
140+
def moveHorizontal(self, level):
141+
self.rect.centerx += self.xDir * self.speed
142+
143+
# Do not walk outside level
144+
if self.rect.left < 0:
145+
self.rect.left = 0
146+
elif self.rect.right > WINDOW_WIDTH:
147+
self.rect.right = WINDOW_WIDTH
148+
149+
self.xPos = self.rect.centerx
150+
151+
152+
def die(self):
153+
if self.currentState != 'DIE':
154+
self.currentState = 'DIE'
155+
self.animationIndex = 0
156+
157+
158+
def checkEnemyCollisions(self, enemies):
159+
# Check for collisions between hero and all enemies in the spritegroup
160+
collidedSprites = pygame.sprite.spritecollide(self, enemies, False)
161+
for enemy in collidedSprites:
162+
if self.currentState == 'ATTACK':
163+
if self.facingRight == True:
164+
if enemy.rect.left < self.rect.right - 30:
165+
enemy.die()
166+
else:
167+
if enemy.rect.right > self.rect.left + 30:
168+
enemy.die()
169+
else:
170+
if enemy.currentState != 'DYING':
171+
if self.rect.left < enemy.rect.left: # Collision on right side
172+
if self.rect.right > enemy.rect.left + 16:
173+
self.die()
174+
elif self.rect.right > enemy.rect.right: # Collision on left side
175+
if self.rect.left < enemy.rect.right - 16:
176+
self.die()
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import pygame
2+
from pytmx.util_pygame import load_pygame
3+
from Config import *
4+
from ClassHero import Hero
5+
from ClassBee import Bee
6+
from ClassTile import Tile
7+
from ClassBackground import Background
8+
9+
10+
class Level():
11+
def __init__(self, displaySurface):
12+
# Load the level tmx file
13+
self.levelData = load_pygame(LEVELS_PATH + "Level1/level.tmx")
14+
15+
# Instantiate classes
16+
self.background = Background()
17+
18+
# Create spriteGroups
19+
self.hero = pygame.sprite.GroupSingle()
20+
self.bees = pygame.sprite.Group()
21+
self.platformTiles = pygame.sprite.Group()
22+
23+
layer = self.levelData.get_layer_by_name('Platforms')
24+
for x, y, tileSurface in layer.tiles():
25+
tile = Tile((x * TILESIZE, y * TILESIZE), tileSurface)
26+
self.platformTiles.add(tile)
27+
28+
self.hero.add(Hero((32, 464), faceRight = True))
29+
self.bees.add(Bee((200, 200), moveRight = True))
30+
self.bees.add(Bee((300, 380), moveRight = False))
31+
32+
self.displaySurface = displaySurface
33+
34+
35+
def update(self):
36+
self.hero.update(self)
37+
self.bees.update(self)
38+
39+
40+
def draw(self):
41+
self.background.draw(self.displaySurface)
42+
self.platformTiles.draw(self.displaySurface)
43+
self.hero.draw(self.displaySurface)
44+
self.bees.draw(self.displaySurface)
45+
46+
47+
def run(self):
48+
self.update()
49+
self.draw()

0 commit comments

Comments
 (0)