1

The problem I am facing is that I have an enemy sprite that is walking on a predetermined path and he needs to keep doing that, but when I press a button he needs to move to the right for example but he still needs to move on the predetermined path. So it's like the predetermined path has to move to the right on a keypress.

This is my code:

import pygame
import random
import os
import time
from random import choices
from random import randint
from pygame.math import Vector2
import itertools

pygame.init()
a = 0
b = 0
width = 1280
height = 720
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption("Game")
done = False
n = 0
x = 0
y = 0
x_wall = 0
y_wall = 0
clock = pygame.time.Clock()
WHITE = (255,255,255)
RED = (255,0,0)
change_x = 0
change_y = 0
HW = width / 2
HH = height / 2
background = pygame.image.load('mountains.png')
x1 = 200
y1 = 100
x2 = 500
y2 = 400
x3 = 100
y3 = 300

#player class
class Player(pygame.sprite.Sprite):
    def __init__(self):
      pygame.sprite.Sprite.__init__(self)
      self.image = pygame.image.load("character.png") 
      self.rect = self.image.get_rect()
      self.rect.x = width / 2
      self.rect.y = height / 2

#enemy class
class Enemy(pygame.sprite.Sprite):

  def __init__(self, pos, waypoints):
    super().__init__()
    self.image = pygame.image.load("enemy.png")
    self.image = pygame.transform.scale(self.image, (int(50), int(50)))
    self.rect = self.image.get_rect(center=pos)
    self.vel = Vector2(0, 0)
    self.max_speed = 5
    self.pos = Vector2(pos)
    self.waypoints = waypoints
    self.waypoint_index = 0
    self.target = self.waypoints[self.waypoint_index]
    self.target_radius = 50
    self.rect.x = width / 2
    self.rect.y = height / 2

  def update(self):

    # A vector pointing from self to the target.
    heading = self.target - self.pos
    distance = heading.length()  # Distance to the target.
    heading.normalize_ip()
    if distance <= 2:  # We're closer than 2 pixels.
      # Increment the waypoint index to swtich the target.
      # The modulo sets the index back to 0 if it's equal to the length.
      self.waypoint_index = (self.waypoint_index + 1) % len(self.waypoints)
      self.target = self.waypoints[self.waypoint_index]
    if distance <= self.target_radius:
            # If we're approaching the target, we slow down.
      self.vel = heading * (distance / self.target_radius * self.max_speed)
    else:  # Otherwise move with max_speed.
      self.vel = heading * self.max_speed

    self.pos += self.vel
    self.rect.center = self.pos


#Enemy waypoints
waypoints = [(x1, y1), (x2, y2), (x3, y3)]
enemy = Enemy((100, 300), waypoints)
all_sprites = pygame.sprite.Group(enemy)



#wall class
class Wall(pygame.sprite.Sprite):
  def __init__(self, x, y):
    pygame.sprite.Sprite.__init__(self)
    self.image = pygame.image.load("wall.png") 
    self.image = pygame.transform.scale(self.image, (int(50), int(50)))
    self.rect = self.image.get_rect()
    self.rect.x = x
    self.rect.y = y

#wall movement
  def update(self):
    self.vx = 0
    self.vy = 0
    key = pygame.key.get_pressed()
    if key[pygame.K_LEFT]:
      self.vx = 5
      self.vy = 0
    elif key[pygame.K_RIGHT]:
      self.vx = -5
      self.vy = 0
    if key[pygame.K_UP]:
      self.vy = 5
      self.vx = 0
    elif key[pygame.K_DOWN]:
      self.vy = -5
      self.vx = 0
    self.rect.x = self.rect.x + self.vx
    self.rect.y = self.rect.y + self.vy

#player sprite group
sprites = pygame.sprite.Group()
player = Player()
sprites.add(player)



#all the wall sprites
wall_list = pygame.sprite.Group()
wall = Wall(x_wall, y_wall)
wall2 = Wall((x_wall + 50), y_wall)
wall3 = Wall((x_wall + 100), y_wall)
wall4 = Wall((x_wall + 150), y_wall)
wall5 = Wall((x_wall + 200), y_wall)
wall6 = Wall((x_wall + 250), y_wall)


#add all the walls to the list to draw them later
wall_list.add(wall, wall2, wall3, wall4, wall5, wall6)

#add all the walls here to fix the collision
all_walls = (wall, wall2, wall3, wall4, wall5, wall6)

while not done:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
    #fill the screen
    screen.fill((0, 0, 0))

    #update sprites
    sprites.update()
    wall_list.update()
    all_sprites.update()


    ##collision between player and and walls
    #if player.rect.collidelist(all_walls) >= 0:
    #  print("Collision !!")
    #  player.rect.x = player.rect.x - player.vx
    #  player.rect.y = player.rect.y - player.vx

    #draw the sprites
    sprites.draw(screen)
    wall_list.draw(screen)
    all_sprites.draw(screen)

    pygame.display.flip()
    clock.tick(30)

pygame.quit()

Here is the download link with the images if you want to run it: https://geordyd.stackstorage.com/s/hZZ1RWcjal6ecZM

Barett
  • 5,826
  • 6
  • 51
  • 55
Geordyd
  • 165
  • 2
  • 10
  • If the `waypoints` are the predetermined path then just increment each point the way you want to when a keypress happens. – Micheal O'Dwyer Jan 06 '18 at 15:37
  • I think you should rather implement a camera. [Here's](https://stackoverflow.com/a/45404355/6220679) a simple solution with a vector. – skrx Jan 07 '18 at 06:24
  • @skrx I used your solution with the vector and now I am having a problem with the collision. Can I ask you a question about that? – Geordyd Jan 07 '18 at 14:50
  • I've updated the first [example](https://stackoverflow.com/a/45404355/6220679). – skrx Jan 08 '18 at 02:19

1 Answers1

1

Inside your update method of the Enemy class add in some input handling to move the waypoints in the event of a keypress.

key = pygame.get_key_pressed()

if key[pygame.K_RIGHT]:
    for i in range(len(waypoints)):
        waypoints[i][0] += 2 # Increment the x value of every waypoint

# Ect

I hope this helped you and if you have any further questions please feel free to comment below.

Micheal O'Dwyer
  • 1,237
  • 1
  • 16
  • 26
  • i tried adding it in but it doesn't work. It says: too many values to unpack (expected 2) – Geordyd Jan 06 '18 at 16:06
  • It seems that you are putting more values than x and y in to the tuples – Micheal O'Dwyer Jan 06 '18 at 16:13
  • Ok there is an issue with my answer which I will update. However, please print out waypoint in the for loop. You should still be able to unpack the tuple. Post what you get below. – Micheal O'Dwyer Jan 06 '18 at 17:44
  • Don't really understand what you mean but if I print waypoints I get this: [(200, 100), (500, 400), (100, 300)] – Geordyd Jan 06 '18 at 17:59
  • That seems to be ok. Try the updated code sample above. The values for waypoints look ok so I think it should work! – Micheal O'Dwyer Jan 06 '18 at 18:01
  • This is the error I get now: TypeError: 'tuple' object does not support item assignment – Geordyd Jan 06 '18 at 18:43
  • Ah yes. I forgot that tuple objects are immutable. Change the round parentheses to square brackets and now they will be lists instead of tuples. Now you will be able to change the values! – Micheal O'Dwyer Jan 06 '18 at 18:45