When i cast a spell the spell moves with me and i don't want it to. I'm circling simple fixes and i feel the answer is in my face but i been staring at it too long. The spell travels but when i move the character the spell follows the direction of the player even as its left the player position. The full code is below
import pygame as py
import sys
from os import path
from settings import *
from sprites import *
from tilemap import *
#HUD
def draw_player_health(surf,x,y,pct):
if pct < 0:
pct = 0
BAR_LENGTH = 100
BAR_HEIGHT = 20
fill = pct * BAR_LENGTH
outline_rect = py.Rect(x,y,BAR_LENGTH,BAR_HEIGHT)
fill_rect = py.Rect(x, y, fill, BAR_HEIGHT)
if pct > 0.6:
color = GREEN
elif pct > 0.3:
color = YELLOW
else:
color = RED
py.draw.rect(surf,color,fill_rect)
py.draw.rect(surf, BLACK, outline_rect, 2)
class Game:
def __init__(self):
py.init()
self.screen = py.display.set_mode((WIDTH, HEIGHT))
py.display.set_caption(TITLE)
self.clock = py.time.Clock()
self.load_data()
def load_data(self):
game_folder = path.dirname(__file__)
self.map = Map(path.join(game_folder, 'img\map.txt'))
self.player_spritesheet = SpriteSheet('img/player_sheet1.png')
self.wall_spritesheet = SpriteSheet('img/woodwall.png')
self.terrain_spritesheet = SpriteSheet('img/grasstexture.jpg')
self.mob_spritesheet = SpriteSheet('img\mobsheet.png')
self.spell_spritesheet = SpriteSheet('img\spellsheethm.png')
def new(self):
# initialize all variables and do all the setup for a new game
self.all_sprites = py.sprite.LayeredUpdates()
self.walls = py.sprite.LayeredUpdates()
self.mobs = py.sprite.LayeredUpdates()
self.spell = py.sprite.LayeredUpdates()
#self.player = py.sprite.LayeredUpdates()
for row, tiles in enumerate(self.map.data):
for col, tile in enumerate(tiles):
Groundtile(self,col,row)
if tile == '1':
Wall(self, col, row)
if tile == 'P':
self.player = Player(self, col, row)
if tile == 'M':
Mobs(self, col, row)
self.camera = Camera(self.map.width, self.map.height)
def run(self):
# game loop - set self.playing = False to end the game
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000
self.events()
self.update()
self.draw()
def quit(self):
py.quit()
sys.exit()
def update(self):
# update portion of the game loop
self.all_sprites.update()
self.camera.update(self.player)
def draw_grid(self):
for x in range(0, WIDTH, TILESIZE):
py.draw.line(self.screen, LIGHTGREY, (x, 0), (x, HEIGHT))
for y in range(0, HEIGHT, TILESIZE):
py.draw.line(self.screen, LIGHTGREY, (0, y), (WIDTH, y))
def draw(self):
self.screen.fill(BGCOLOR)
# self.draw_grid()
for sprite in self.all_sprites:
if isinstance(sprite, Mobs):
sprite.draw_health()
self.screen.blit(sprite.image, self.camera.apply(sprite))
#HUD
draw_player_health(self.screen,850, 10, self.player.health / PLAYER_HEALTH)
py.display.flip()
def events(self):
# catch all events here
for event in py.event.get():
if event.type == py.QUIT:
self.quit()
if event.type == py.KEYDOWN:
if event.key == py.K_ESCAPE:
self.quit()
if event.key == py.K_SPACE:
if self.player.facing == 'up':
Spells(self, self.player.rect.x, self.player.rect.y)
if self.player.facing == 'down':
Spells(self, self.player.rect.x, self.player.rect.y)
if self.player.facing == 'left':
Spells(self, self.player.rect.x, self.player.rect.y)
if self.player.facing == 'right':
Spells(self, self.player.rect.x, self.player.rect.y)
def show_start_screen(self):
pass
def show_go_screen(self):
pass
# create the game object
g = Game()
g.show_start_screen()
while True:
g.new()
g.run()
g.show_go_screen()
if self.y_change == 0:
self.image = self.game.player_spritesheet.get_sprite(2, 71, self.width,self.height)
else:
self.image = up_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 4:
self.animate_loop = 1
if self.facing == "right":
if self.x_change == 0:
self.image = self.game.player_spritesheet.get_sprite(6, 37, self.width,self.height)
else:
self.image = right_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 4:
self.animate_loop = 1
if self.facing == "left":
if self.x_change == 0:
self.image = self.game.player_spritesheet.get_sprite(7, 180, self.width,self.height)
else:
self.image = left_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 4:
self.animate_loop = 1
def mob_collide(self):
hits = py.sprite.spritecollide(self.game.player,self.game.mobs, False)
for hit in hits:
self.health -= MOB_DMG
def update(self):
self.get_keys()
self.animation()
self.mob_collide()
self.rect.x += self.x_change
self.collide_with_walls('x')
self.rect.y += self.y_change
self.collide_with_walls('y')
self.x_change = 0
self.y_change = 0
if self.health <= 0:
self.kill()
class Mobs(py.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = MOB_LAYER
self.groups = self.game.all_sprites, self.game.mobs
py.sprite.Sprite.__init__(self, self.groups)
self.x = x * TILESIZE
self.y = y * TILESIZE
self.width = TILESIZE
self.height = TILESIZE
self.facing = random.choice(['up','down','left','right'])
self.animate_loop = 1
self.movement_loop = 0
self.max_travel = random.randint(0,200)
self.x_change = 0
self.y_change = 0
self.image = self.game.mob_spritesheet.get_sprite(0,11,self.width,self.height)
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
self.health = MOB_HEALTH
def update(self):
self.movement()
self.animation()
self.rect.x += self.x_change
self.collide_with_walls('x')
self.rect.y += self.y_change
self.collide_with_walls('y')
self.x_change = 0
self.y_change = 0
if self.health <= 0:
self.kill()
#self.player_collide()
def draw_health(self):
if self.health > 60:
color = GREEN
elif self.health > 30:
color = YELLOW
else:
color = RED
width = int(self.rect.width * self.health / MOB_HEALTH)
self.health_bar = py.Rect(0,0, width, 7)
if self.health < MOB_HEALTH:
py.draw.rect(self.image, color, self.health_bar)
def collide_with_walls(self, dir):
if dir == 'x':
hits = py.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.x_change > 0:
self.x = hits[0].rect.left - self.rect.width
if self.x_change < 0:
self.x = hits[0].rect.right
self.x_change = 0
self.rect.x = self.x
if dir == 'y':
hits = py.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.y_change > 0:
self.y = hits[0].rect.top - self.rect.height
if self.y_change < 0:
self.y = hits[0].rect.bottom
self.y_change = 0
self.rect.y = self.y
def movement(self):
if self.facing == 'left':
self.x_change -= MOB_SPEED
self.movement_loop -= 1
if self.movement_loop <= -self.max_travel:
self.facing = 'right'
if self.facing == 'right':
self.x_change += MOB_SPEED
self.movement_loop += 1
if self.movement_loop >= self.max_travel:
self.facing = 'left'
if self.facing == 'up':
self.y_change -= MOB_SPEED
self.movement_loop -= 1
if self.movement_loop <= -self.max_travel:
self.facing = 'down'
if self.facing == 'down':
self.y_change += MOB_SPEED
self.movement_loop += 1
if self.movement_loop >= self.max_travel:
self.facing = 'up'
def animation(self):
down_animations = [self.game.mob_spritesheet.get_sprite(0, 11, self.width, self.height),
self.game.mob_spritesheet.get_sprite(33, 11, self.width, self.height),
self.game.mob_spritesheet.get_sprite(65, 11, self.width, self.height)]
up_animations = [self.game.mob_spritesheet.get_sprite(2, 218, self.width, self.height),
self.game.mob_spritesheet.get_sprite(33, 218, self.width, self.height),
self.game.mob_spritesheet.get_sprite(65, 218, self.width, self.height)]
left_animations = [self.game.mob_spritesheet.get_sprite(3, 70, self.width, self.height),
self.game.mob_spritesheet.get_sprite(35, 70, self.width, self.height),
self.game.mob_spritesheet.get_sprite(67, 70, self.width, self.height)]
right_animations = [self.game.mob_spritesheet.get_sprite(3, 130, self.width, self.height),
self.game.mob_spritesheet.get_sprite(35, 130, self.width, self.height),
self.game.mob_spritesheet.get_sprite(67, 130, self.width, self.height)]
if self.facing == "down":
if self.y_change == 0:
self.image = self.game.mob_spritesheet.get_sprite(2, 1, self.width,self.height)
else:
self.image = down_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 3:
self.animate_loop = 1
if self.facing == "up":
if self.y_change == 0:
self.image = self.game.mob_spritesheet.get_sprite(2, 71, self.width,self.height)
else:
self.image = up_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 3:
self.animate_loop = 1
if self.facing == "right":
if self.x_change == 0:
self.image = self.game.mob_spritesheet.get_sprite(6, 37, self.width,self.height)
else:
self.image = right_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 3:
self.animate_loop = 1
if self.facing == "left":
if self.x_change == 0:
self.image = self.game.mob_spritesheet.get_sprite(7, 180, self.width,self.height)
else:
self.image = left_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.1
if self.animate_loop >= 3:
self.animate_loop = 1
class Spells(py.sprite.Sprite):
def __init__(self, game,x,y):
self.game = game
self._layer = SPELL_LAYER
self.groups = self.game.all_sprites, self.game.spell
py.sprite.Sprite.__init__(self, self.groups)
self.x = x
self.y = y
self.width = TILESIZE
self.height = TILESIZE
self.movement_loop = 0
self.shoodir = 'down'
self.animate_loop = 0
# self.spawn_time = py.time.get_ticks()
self.image = self.game.spell_spritesheet.get_sprite(4,14,self.width,self.height)
self.image.set_colorkey(WHITE)
self.x_change = 0
self.y_change = 0
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
def update(self):
self.animate()
self.collide()
self.rect.x += self.x_change
self.collide_with_walls('x')
self.rect.y += self.y_change
self.collide_with_walls('y')
self.x_change = 0
self.y_change = 0
self.movement()
#if py.time.get_ticks() - self.spawn_time > SPELL_LIFETIME:
# self.kill()
def collide(self):
hits = py.sprite.groupcollide(self.game.mobs,self.game.spell, False, True)
for hit in hits:
hit.health -= SPELL_DMG
def collide_with_walls(self, dir):
if dir == 'x':
hits = py.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.x_change > 0:
self.x = hits[0].rect.left - self.rect.width
self.kill()
if self.x_change < 0:
self.x = hits[0].rect.right
self.kill()
self.x_change = 0
self.rect.x = self.x
if dir == 'y':
hits = py.sprite.spritecollide(self, self.game.walls, False)
if hits:
if self.y_change > 0:
self.y = hits[0].rect.top - self.rect.height
self.kill()
if self.y_change < 0:
self.y = hits[0].rect.bottom
self.kill()
self.y_change = 0
self.rect.y = self.y
def animate(self):
direction = self.game.player.facing
down_animations = [self.game.spell_spritesheet.get_sprite(0, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(35, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(67, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(98, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(128, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(158, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(190, 0, self.width, self.height)]
up_animations = [self.game.spell_spritesheet.get_sprite(0, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(35, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(67, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(98, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(128, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(158, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(190, 0, self.width, self.height)]
left_animations = [self.game.spell_spritesheet.get_sprite(0, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(35, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(67, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(98, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(128, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(158, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(190, 0, self.width, self.height)]
right_animations = [self.game.spell_spritesheet.get_sprite(0, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(35, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(67, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(98, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(128, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(158, 0, self.width, self.height),
self.game.spell_spritesheet.get_sprite(190, 0, self.width, self.height)]
if direction == 'up':
self.image = up_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.5
if self.animate_loop >= 7:
self.animate_loop = 1
if direction == 'down':
self.image = down_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.5
if self.animate_loop >= 7:
#self.kill()
self.animate_loop = 1
if direction == 'left':
self.image = left_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.5
if self.animate_loop >= 7:
#self.kill()
self.animate_loop = 1
if direction == 'right':
self.image = right_animations[math.floor(self.animate_loop)]
self.animate_loop += 0.5
if self.animate_loop >= 7:
#self.kill()
self.animate_loop = 1
def movement(self):
direction = self.game.player.facing
if direction == 'left':
self.shoodir = 'left'
self.x_change -= SPELL_SPEED
self.movement_loop -= 1
if self.movement_loop == -SPELL_LIFETIME:
self.kill()
if direction == 'right':
self.shoodir = 'right'
self.x_change += SPELL_SPEED
self.movement_loop += 1
if self.movement_loop == SPELL_LIFETIME:
self.kill()
if direction == 'up':
self.shoodir = 'up'
self.y_change -= SPELL_SPEED
self.movement_loop -= 1
if self.movement_loop == -SPELL_LIFETIME:
self.kill()
if direction == 'down':
self.shoodir = 'down'
self.y_change += SPELL_SPEED
self.movement_loop += 1
if self.movement_loop == SPELL_LIFETIME:
self.kill()
class Wall(py.sprite.Sprite):
def __init__(self, game, x, y):
self.game = game
self._layer = BLOCK_LAYER
self.groups = self.game.all_sprites, self.game.walls
py.sprite.Sprite.__init__(self, self.groups)
self.x = x * TILESIZE
self.y = y * TILESIZE
self.width = TILESIZE
self.height = TILESIZE
self.image = self.game.wall_spritesheet.get_sprite(0,0,self.width,self.height)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
def update(self):
self.rect.x += self.x_change
self.rect.y += self.y_change
self.x_change = 0
self.y_change = 0
class Groundtile(py.sprite.Sprite):
def __init__(self, game, x , y):
self.game = game
self._layer = GROUND_LAYER
self.groups = self.game.all_sprites
py.sprite.Sprite.__init__(self, self.groups)
self.x = x * TILESIZE
self.y = y * TILESIZE
self.width = TILESIZE
self.height = TILESIZE
self.image = self.game.terrain_spritesheet.get_sprite(0,0,self.width,self.height)
self.rect = self.image.get_rect()
self.rect.x = self.x
self.rect.y = self.y
import pygame as py
from settings import *
def collide_hit_rect(one, two):
return one.hit_rect.colliderect(two.rect)
class Map:
def __init__(self, filename):
self.data = []
with open(filename, 'rt') as f:
for line in f:
self.data.append(line.strip())
self.tilewidth = len(self.data[0])
self.tileheight = len(self.data)
self.width = self.tilewidth * TILESIZE
self.height = self.tileheight * TILESIZE
class Camera:
def __init__(self, width, height):
self.camera = py.Rect(0, 0, width, height)
self.width = width
self.height = height
def apply(self, entity):
return entity.rect.move(self.camera.topleft)
def update(self, target):
x = -target.rect.x + int(WIDTH / 2)
y = -target.rect.y + int(HEIGHT / 2)
# limit scrolling to map size
x = min(0, x) # left
y = min(0, y) # top
x = max(-(self.width - WIDTH), x) # right
y = max(-(self.height - HEIGHT), y) # bottom
self.camera = py.Rect(x, y, self.width, self.height)
///////SETTINGS FILE//////////
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
DARKGREY = (40, 40, 40)
LIGHTGREY = (100, 100, 100)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
# game settings
WIDTH = 1024 # 16 * 64 or 32 * 32 or 64 * 16
HEIGHT = 768 # 16 * 48 or 32 * 24 or 64 * 12
FPS = 60
TITLE = "ZomBlaster"
BGCOLOR = DARKGREY
TILESIZE = 32
GRIDWIDTH = WIDTH / TILESIZE
GRIDHEIGHT = HEIGHT / TILESIZE
# Player settings
PLAYER_SPEED = 3
PLAYER_HEALTH = 10000
#Loading Layers
PLAYER_LAYER = 4
MOB_LAYER = 3
BLOCK_LAYER = 2
GROUND_LAYER = 1
SPELL_LAYER = 4
#Mob settings
MOB_HEALTH = 100
MOB_SPEED = 1
MOB_DMG = 10
MOB_KNOCKBACK = 2
#Spell settings
SPELL_IMG1 = ''
SPELL_SPEED = 5
SPELL_LIFETIME = 2000
SPELL_RATE = 10
SPELL_DMG = 10
def animate(self):
direction = self.game.player.facing
def movement(self):
direction = self.game.player.facing
These lines of code seem to modify the direction of the spell depending on direction of character every time the "animate" or "movement" methods are called.
I quickly glanced through the code looking for definition of "game.player" but I guess I may be missing it, however, I making an assumption that this is the player of the game your question is referring to.
Since your direction is modified by the player's direction, you've modified the "shootdir" if your spell, as well as the animations, extra logic etc.
I might suggest using an extra variable in your class constructor with a cardinal direction that is otherwise not modifiable through your methods. Such as:
class Spells(py.sprite.Sprite):
def __init__(self, game,x,y, direction):
self.game = game
self._layer = SPELL_LAYER
self.groups = self.game.all_sprites, self.game.spell
self.direction = direction
py.sprite.Sprite.__init__(self, self.groups)
and call it like so:
def events(self):
# catch all events here
for event in py.event.get():
if event.type == py.QUIT:
self.quit()
if event.type == py.KEYDOWN:
if event.key == py.K_ESCAPE:
self.quit()
if event.key == py.K_SPACE:
if self.player.facing == 'up':
Spells(self, self.player.rect.x, self.player.rect.y,
self.player.facing)
if self.player.facing == 'down':
Spells(self, self.player.rect.x, self.player.rect.y,
self.player.facing)
if self.player.facing == 'left':
Spells(self, self.player.rect.x, self.player.rect.y,
self.player.facing)
if self.player.facing == 'right':
Spells(self, self.player.rect.x, self.player.rect.y,
self.player.facing)