Catapults working. At this point most of the basic game is set up, now I have to get down to level and enemy creation, and sounds for when things happen.
This commit is contained in:
		
							
								
								
									
										137
									
								
								src/catapult.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/catapult.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| from libstormgames import * | ||||
| from src.object import Object | ||||
| import random | ||||
|  | ||||
|  | ||||
| class Pumpkin: | ||||
|     def __init__(self, x, isHigh, direction, playerMaxHealth): | ||||
|         self.x = x | ||||
|         self.isHigh = isHigh | ||||
|         self.direction = direction  # 1 for right, -1 for left | ||||
|         self.speed = 0.15 | ||||
|         self.isActive = True | ||||
|         self.damage = playerMaxHealth // 2  # Half of player's max health | ||||
|         self.soundChannel = None | ||||
|         self.soundName = 'pumpkin_low' if isHigh else 'pumpkin_high'  # Inverted mapping | ||||
|  | ||||
|     def update(self, sounds, playerX): | ||||
|         """Update pumpkin position and sound""" | ||||
|         if not self.isActive: | ||||
|             return False | ||||
|          | ||||
|         self.x += self.direction * self.speed | ||||
|          | ||||
|         # Update or start positional audio | ||||
|         if self.soundChannel is None or not self.soundChannel.get_busy(): | ||||
|             self.soundChannel = obj_play(sounds, self.soundName, playerX, self.x) | ||||
|         else: | ||||
|             self.soundChannel = obj_update(self.soundChannel, playerX, self.x) | ||||
|              | ||||
|         return True | ||||
|  | ||||
|     def stop_sound(self): | ||||
|         """Stop the pumpkin's sound""" | ||||
|         if self.soundChannel: | ||||
|             obj_stop(self.soundChannel) | ||||
|             self.soundChannel = None | ||||
|  | ||||
|     def check_collision(self, player): | ||||
|         """Check if pumpkin hits player""" | ||||
|         if not self.isActive: | ||||
|             return False | ||||
|              | ||||
|         distance = abs(player.xPos - self.x) | ||||
|         if distance < 1:  # Within 1 tile | ||||
|             if self.isHigh and not player.isJumping: | ||||
|                 return True  # Hit by high pumpkin while on ground | ||||
|             elif not self.isHigh and player.isJumping: | ||||
|                 return True  # Hit by low pumpkin while jumping | ||||
|         return False | ||||
|  | ||||
|  | ||||
| class Catapult(Object): | ||||
|     def __init__(self, x, y, sounds, direction=1, fireInterval=5000, firingRange=20): | ||||
|         super().__init__( | ||||
|             x, y, "catapult", | ||||
|             isStatic=True, | ||||
|             isCollectible=False, | ||||
|         ) | ||||
|         self.sounds = sounds | ||||
|         self.direction = direction | ||||
|         self.fireInterval = fireInterval  # Time between shots in milliseconds | ||||
|         self.firingRange = firingRange  # How close player needs to be to trigger firing | ||||
|         self.lastFireTime = 0 | ||||
|         self.activePumpkins = [] | ||||
|         self.isFiring = False  # Track if we're currently in firing mode | ||||
|         self.launchDelay = 900  # Time between launch sound and pumpkin firing | ||||
|         self.pendingPumpkin = None  # Store pending pumpkin data | ||||
|         self.pumpkinLaunchTime = 0  # When to launch the pending pumpkin | ||||
|  | ||||
|     def fire(self, currentTime, player): | ||||
|         """Start the firing sequence""" | ||||
|         self.lastFireTime = currentTime | ||||
|          | ||||
|         # Play launch sound | ||||
|         self.sounds['catapult_launch'].play() | ||||
|          | ||||
|         # Set up pending pumpkin | ||||
|         isHigh = random.choice([True, False]) | ||||
|         fireDirection = 1 if player.xPos > self.xPos else -1 | ||||
|          | ||||
|         # Store pumpkin data for later creation | ||||
|         self.pendingPumpkin = { | ||||
|             'isHigh': isHigh, | ||||
|             'direction': fireDirection, | ||||
|             'playerMaxHealth': player.get_max_health() | ||||
|         } | ||||
|          | ||||
|         # Set when to actually launch the pumpkin | ||||
|         self.pumpkinLaunchTime = currentTime + self.launchDelay | ||||
|  | ||||
|     def update(self, currentTime, player): | ||||
|         """Update catapult and its pumpkins""" | ||||
|         if not self.isActive: | ||||
|             return | ||||
|              | ||||
|         # Check if player is in range | ||||
|         distance = abs(player.xPos - self.xPos) | ||||
|         inRange = distance <= self.firingRange | ||||
|          | ||||
|         # Handle entering/leaving range | ||||
|         if inRange and not self.isFiring: | ||||
|             self.isFiring = True | ||||
|             self.lastFireTime = currentTime  # Reset timer when entering range | ||||
|             speak("Pumpkin catapult activates!") | ||||
|         elif not inRange and self.isFiring: | ||||
|             self.isFiring = False | ||||
|             speak("Out of pumpkin catapult range.") | ||||
|              | ||||
|         # Check for pending pumpkin launch | ||||
|         if self.pendingPumpkin and currentTime >= self.pumpkinLaunchTime: | ||||
|             # Create and fire the pending pumpkin | ||||
|             pumpkin = Pumpkin( | ||||
|                 self.xPos, | ||||
|                 self.pendingPumpkin['isHigh'], | ||||
|                 self.pendingPumpkin['direction'], | ||||
|                 self.pendingPumpkin['playerMaxHealth'] | ||||
|             ) | ||||
|             self.activePumpkins.append(pumpkin) | ||||
|             self.pendingPumpkin = None | ||||
|              | ||||
|         # Only start new fire sequence if in range and enough time has passed | ||||
|         if self.isFiring and currentTime - self.lastFireTime >= self.fireInterval: | ||||
|             self.fire(currentTime, player) | ||||
|              | ||||
|         # Always update existing pumpkins | ||||
|         for pumpkin in self.activePumpkins[:]:  # Copy list to allow removal | ||||
|             if not pumpkin.update(self.sounds, player.xPos): | ||||
|                 pumpkin.stop_sound() | ||||
|                 self.activePumpkins.remove(pumpkin) | ||||
|                 continue | ||||
|                  | ||||
|             if pumpkin.check_collision(player): | ||||
|                 player.set_health(player.get_health() - pumpkin.damage) | ||||
|                 pumpkin.stop_sound() | ||||
|                 pumpkin.isActive = False | ||||
|                 self.activePumpkins.remove(pumpkin) | ||||
|                 speak("Hit by a pumpkin!") | ||||
		Reference in New Issue
	
	Block a user