I have been tasked with producing a simple program that simulates the actions of a vehicle from a list of command stored & accessed within a text file.
The expected output would look something like this;
Loading simulation...
Accelerating...
Speed = 5, Gear = 1, Direction = 0
Accelerating...
Speed = 10, Gear = 1, Direction = 0
Accelerating...
Changing up...
Current gear = 2
Speed = 15, Gear = 2, Direction = 0
Accelerating...
Speed = 20, Gear = 2, Direction = 0
Accelerating...
Yet my output looks like this;
Loading Simulation....
Car Gear is First (1)
Accelerating...
Car Gear is First (1)
Speed = 5, Gear = 1, Direction = [-1, 0, 1]
Braking...
Car Gear is First (1)
Speed = 0, Gear = 1, Direction = [-1, 0, 1]
Car Gear is First (1)
Accelerating...
Car Gear is First (1)
Speed = 5, Gear = 1, Direction = [-1, 0, 1]
Braking...
Car Gear is First (1)
Speed = 0, Gear = 1, Direction = [-1, 0, 1]
Car Gear is First (1)
When I run my code in Idle, i get no errors of any kind, when i use Thonny, it gives me the folloing error when it analyses the code:
Line 113 : Either all return statements in a function should return an expression, or none of them should.
Line 113 : Unused argument 'selected_gear'
Below is a copy of my code also:
RIGHT = 1
LEFT = -1
FORWARD = 1
REVERSE = 0
STRAIGHT = 0
#gears and allowable speeds are as follows:
#zero (reverse) (speed -1 to -10). Max reverse speed of car is -10
#one (speed 0 to 10)
#two (speed 10 to 20)
#three (speed 20 to 30)
#four (speed 30 to 45)
#five (speed 45 to 80). Max speed of car is 80
#gears change automatically, one gear at a time
#direction values are similar to numbers on clock face
#0 = 12 = straight on. All other directions = 1-11
class Car:
def __init__(self):
self.speed = 0
self.gear = [0,1,2,3,4,5]
self.direction = [-1,0,1]
self.broken = False #indicates whether car is broken
self.simulation = []
self.simulation_loaded = False
def accelerate(self):
if self.broken:
print("Car is broken!")
return
print("Accelerating...")
if self.gear == REVERSE:
self.speed -= 5
else:
self.speed += 5
if self.speed > 80:
self.speed = 80
if self.speed < -10:
self.speed = -10
self.change_gear(self.gear)
self.display_stats()
def brake(self):
if self.broken:
print("Car is broken...")
return
print("Braking...")
if self.speed < 0:
self.speed += 5
if self.speed > 0:
self.speed = 0
elif self.speed > 0:
self.speed -= 5
if self.speed < 0:
self.speed = 0
self.change_gear(self.gear)
self.display_stats()
def turn_steering_wheel(self, direction_change):
if self.broken:
print("Car is broken...")
return
if self.gear == REVERSE:
print ("Car is in reverse...")
if direction_change == RIGHT:
self.direction = -1
print("Reversing Right")
elif direction_change == REVERSE:
self.direction = 12
print("Reversing")
elif direction_change == LEFT:
self.direction = 1
print("Reversing Left")
elif self.gear == FORWARD:
if direction_change == LEFT:
self.direction = -1
print("Turning Left")
elif direction_change == STRAIGHT:
self.direction = 0
print("Moving Forward")
elif direction_change == RIGHT:
self.direction = 1
print("Turning Right")
self.display_stats()
def change_gear(self, selected_gear = FORWARD):
if self.broken:
print("Car is broken...")
return self.broken
# if self.gear == 0 and self.speed >= 0:
# print("you are going forward while in reverse gear...")
# return self.broken
# elif self.gear >= 1 and self.speed <= -1:
# print("you are going reverse while in foward gear...")
# return self.broken
if self.speed <= -1:
self.gear = 0
print("Car Gear is Neutral (0)")
return self.gear
elif self.speed <= 10:
self.gear = 1
print("Car Gear is First (1)")
return
elif self.speed <= 20:
self.gear = 2
print("Car Gear is Second (2)")
return
elif self.speed <= 30:
self.gear = 3
print("Car Gear is Third (3)")
return
elif self.speed <= 40:
self.gear = 4
print("Car Gear is Fourth (4)")
return
elif self.speed <= 50:
self.gear = 5
print("Car Gear is Fifth (5)")
return
self.display_stats()
self.change_gear(self.gear)
#check to see if car is going forward when reverse is selected and vice versa
#work out what gear you need to be in based on car’s speed
#Loop one gear at a time, either changing up or down, to get to required gear
print("Changing up...")
def display_stats(self):
print(f"Speed = {self.speed}, Gear = {self.gear}, Direction = {self.direction}")
def load_simulation(self, filename):
file = open(filename)
line = file.readline()
while line !='':
self.simulation.append(line.strip())
line = file.readline()
file.close()
self.simulation_loaded = True
return self.simulation
def run_simulation(self):
if self.simulation_loaded == False:
print("Error - Simulation.txt file is present")
else:
print("Loading Simulation....")
for action in self.simulation:
if action == "FORWARD":
self.change_gear (FORWARD)
elif action == "ACCELERATE":
self.accelerate()
elif action == "LEFT":
#self.direction(LEFT)
print("TURNING LEFT")
elif action == "RIGHT":
#self.direction(RIGHT)
print("TURNING RIGHT")
'''***WHEN USING SELF.DIRECTION(LEFT)/(RIGHT) the following error is given:
Traceback (most recent call last):
File "C:\Users\lenovo\Desktop\Bsc Computer Forensics - Laptop\Software-Dev\car-temp-2.py", line 207, in <module>
my_car.run_simulation()
File "C:\Users\lenovo\Desktop\Bsc Computer Forensics - Laptop\Software-Dev\car-temp-2.py", line 183, in run_simulation
self.direction(LEFT)
TypeError: 'list' object is not callable*** '''
elif action == "BRAKE":
self.brake()
else:
self.change_gear (REVERSE)
if __name__ == '__main__':
my_car = Car()
my_car.load_simulation("simulation.txt")
my_car.run_simulation()
Would I please be able to ask if anyone could explain what the errors im getting mean and where in my code I need to be looking, its got me feeling a little lost now - I've tried to research them, fix them but anyhting I try either seems to have no impact or gives errors that otherwise don't exist.
The errors occur in your change_gear() function, although they are more like warnings and should not pose serious problems:
Line 113 : Either all return statements in a function should return an expression, or none of them should.
The first two return statements return a value while the others don't. This is inconsistent and makes the code harder to understand. Since you don't actually use the returned values anywhere, you can remove them (i.e. use plain return).
Line 113 : Unused argument 'selected_gear'
You don't use the selected_gear argument anywhere inside change_gear(). You can remove it to get rid of the warning/error.
Related
I have a bunch of different bullets with different list and I wondering if I could shorten the way of doing this without copying and pasting and making thousands of lines of code.
the code is checking if all those bullets list are collided with the enemy sprite
is there way I could put a list in a list or something so I dont have to write all these code
for example
I have
bullet1 = []
bullet2 = []
bullet3 = []
# and store all those bullet in another list?
all_bullets = [bullet1,bullet2,bullet3] is that possibale?
def upgrade_tower_1():
if upgrade1.x == 9000:
collid_1 = False
for monster in monsters:
for shootss in shootsright:
if monster.rect.colliderect(shootss.rect):
collid_1 = False
monster.direction = "hit"
if monster.health > 2:
monster.health -= 0.2
else:
monster.x = void.x + 20
monster.y = void.y + 150
money1.cash += 5
if upgrade5.x == 9000:
collid_1 = False
for monster in monsters:
for shootss in shootsright:
if monster.rect.colliderect(shootss.rect):
collid_1 = False
monster.direction = "hit"
if monster.health > 2:
monster.health -= 0.3
else:
monster.x = void.x + 20
monster.y = void.y + 150
money1.cash += 5
if upgrade5.x == 9000:
collid_1 = False
for monster in monsters:
for shootss2 in shootsright2:
if monster.rect.colliderect(shootss2.rect):
collid_1 = False
monster.direction = "hit"
if monster.health > 2:
monster.health -= 0.3
else:
monster.x = void.x + 20
monster.y = void.y + 150
money1.cash += 5
I recommend to write a function (or a method) that tests for collisions between shootsright and monsters:
def detect_collision(monsterlist, shootlist, money):
collide = False
for monster in monsterlist:
for shootss in shootlist:
if monster.rect.colliderect(shootss.rect):
collide = False # True ?
monster.direction = "hit"
if monster.health > 2:
monster.health -= 0.2
else:
monster.x = void.x + 20
monster.y = void.y + 150
money.cash += 5
return collide
Instead of duplicating the code, call the function:
if upgrade1.x == 9000:
collid_1 = detect_collision(monsters, shootsright, money1)
# [...]
if upgrade5.x == 9000:
collid_1 = detect_collision(monsters, shootsright, money1)
# [...]
if upgrade5.x == 9000:
collid_1 = detect_collision(monsters, shootsright2, money1)
# [...]
I just currently finished making the game 'snake' as a practice to learn how to program, as I am new to programming for about 3 months.
Although the game is completed and runs the way I intended, I want to try to simplify my code and reduce the amount of lines as much as possible, and possibly make the script tidier as the current majority of my codes are cluster in the while loop.
Until now I haven't touched upon class objects, and I want everything in the while loop to go into individual classes that get called out from the while loop to reduce the amount of lines in it.
off-topic: by reading through the script, how else can I improve it to be run more efficiently, including simplifying some code as I may have over-complicated it?
I looked up how class object is used from w3school and other programming tutorials, but I still don't fully understand it as it only shows examples in using print. I did play around and experimented with class object examples and attempted to call them without using print, but I lack the knowledge of how to use them properly.
from graphics import *
from threading import Timer
import keyboard, random, time
# configurations
width = 400
gridHeight = width
height = 470
timer = False
game = True
score = 0
bonus = 0
x = 70
y = 30
radius = 10
length = radius * 2
playerLength = 3
poisonLength = playerLength
i = 0
k = 0
pointRadius = 5
points = False
cherryPoints = False
key = "Right"
countDown = 0
# set coordinations
cX = 90
cY = 30
coordX = [10]
coordY = [10]
while coordX[len(coordX)-1] != width-10:
cX+=20
coordX.append(cX)
while coordY[len(coordY)-1] != 390:
cY+=20
coordY.append(cY)
randomX = random.choice(coordX)
randomY = random.choice(coordY)
cherryRandomX = random.choice(coordX)
cherryRandomY = random.choice(coordY)
poisonRandomX = random.choice(coordX)
poisonRandomY = random.choice(coordY)
# window set up
win = GraphWin("SNAKE", width, height, autoflush = False)
win.setBackground(color_rgb(15,15,15))
# grid
lineX = 20
while lineX < width:
gridX = Line(Point(lineX,0),Point(lineX,gridHeight))
gridX.setOutline(color_rgb(25,25,25))
gridX.draw(win)
lineX += 20
lineY = 20
while lineY <= gridHeight:
gridX = Line(Point(0,lineY),Point(width,lineY))
gridX.setOutline(color_rgb(25,25,25))
gridX.draw(win)
lineY += 20
# snake banner
UI = Rectangle(Point(0,400),Point(width,height))
UI.setFill(color_rgb(102,51,0))
UI.setOutline(color_rgb(102,51,0))
UI.draw(win)
snakeTitle = Text(Point(width/2,420),"SNAKE")
snakeTitle.setTextColor("green")
snakeTitle.setSize(20)
snakeTitle.draw(win)
scoreTitle = Text(Point(320,424),"SCORE")
scoreTitle.setTextColor("white")
scoreTitle.setSize(10)
scoreTitle.draw(win)
scoreUI = Text(Point(320,435),score)
scoreUI.setTextColor("white")
scoreUI.setSize(10)
scoreUI.draw(win)
# make player
player = {}
player[0] = Rectangle(Point(x-20-radius,y-radius), Point(x-20+radius, y+radius))
player[1] = Rectangle(Point(x-40-radius,y-radius), Point(x-40+radius, y+radius))
player[2] = Rectangle(Point(x-60-radius,y-radius), Point(x-60+radius, y+radius))
# make poison
poison = {}
def main():
global timer, scoreUI, score, bonus, playerLength, poisonLength, x, y, points, cherryPoints, randomX, randomY, cherryRandomX, cherryRandomY, poisonRandomX, poisonRandomY, key, countDown, k, game
while(game==True):
# score update
scoreUI.undraw()
scoreUI = Text(Point(320,435),score)
scoreUI.setTextColor("white")
scoreUI.setSize(10)
scoreUI.draw(win)
# generating new body blocks
if len(player) < playerLength:
i+=1
player[i] = player[i-1].clone()
# body following player
player[0].undraw()
for i in range(1,len(player)):
player[len(player)-i].undraw()
player[len(player)-i] = player[len(player)-i-1].clone()
player[len(player)-i].draw(win)
# update player's head coordinate
player[0] = Rectangle(Point(x-radius,y-radius), Point(x+radius,y+radius))
player[0].setFill("green")
player[0].setWidth(2)
player[0].draw(win)
# player movement
if keyboard.is_pressed("Up") and key != "Down":
key = "Up"
elif keyboard.is_pressed("Left") and key != "Right":
key = "Left"
elif keyboard.is_pressed("Down") and key != "Up":
key = "Down"
elif keyboard.is_pressed("Right") and key != "Left":
key = "Right"
if key == "Up":
y -= length
elif key == "Left":
x -= length
elif key == "Down":
y += length
elif key == "Right":
x += length
# point
if points == False: # generates new point when eaten
point = Rectangle(Point(randomX-pointRadius,randomY-pointRadius),Point(randomX+pointRadius,randomY+pointRadius))
point.setFill("white")
point.setWidth(2)
point.draw(win)
points = True
if player[0].getCenter().getX() == point.getCenter().getX() and player[0].getCenter().getY() == point.getCenter().getY(): # when player eats the point
point.undraw()
playerLength += 1
poisonLength += 1
score += 200+bonus
randomX = random.choice(coordX)
randomY = random.choice(coordY)
for i in range(len(player)):
if (point.getCenter().getX() == player[i].getCenter().getX() and point.getCenter().getY() == player[i].getCenter().getY()) or (cherryPoints == True and cherryPoint.getCenter().getX() == point.getCenter().getX() and cherryPoint.getCenter().getY() == point.getCenter().getY()): # regenerate x and y coordinate if they share the same coordinate as player and cherry
randomX = random.choice(coordX)
randomY = random.choice(coordY)
for i in range(len(poison)): # regenerate x and y coordinate if point shares the same coordinate to other array of poisons
if point.getCenter().getX() == poison[i].getCenter().getX() and point.getCenter().getY() == poison[i].getCenter().getY():
cherryRandomX = random.choice(coordX)
cherryRandomY = random.choice(coordY)
points = False
# cherry
if countDown == 150:
countDown = 0
if cherryPoints == False: # generates new cherry from countdown
cherryPoint = Rectangle(Point(cherryRandomX-pointRadius,cherryRandomY-pointRadius),Point(cherryRandomX+pointRadius,cherryRandomY+pointRadius))
cherryPoint.setFill(color_rgb(213,0,50))
cherryPoint.setWidth(2)
cherryPoint.draw(win)
cherryPoints = True
if cherryPoints == True:
for i in range(2, 6): # cherry blinks between countdown 40 to 100
if countDown == 20*i:
cherryPoint.undraw()
elif countDown == 10+(20*i):
cherryPoint.draw(win)
if countDown >= 100: # when countdown becomes 100, remove cherry and reset count down
cherryPoints = False
countDown = 0
cherryRandomX = random.choice(coordX)
cherryRandomY = random.choice(coordY)
if cherryPoints==True and player[0].getCenter().getX() == cherryPoint.getCenter().getX() and player[0].getCenter().getY() == cherryPoint.getCenter().getY(): # when player eats the cherry
cherryPoint.undraw()
score += 500
cherryRandomX = random.choice(coordX)
cherryRandomY = random.choice(coordY)
for i in range(len(player)):
if (cherryPoint.getCenter().getX() == player[i].getCenter().getX() and cherryPoint.getCenter().getY() == player[i].getCenter().getY()) or (cherryPoint.getCenter().getX() == point.getCenter().getX() and cherryPoint.getCenter().getY() == point.getCenter().getY()): # regenerate x and y coordinate if they share the same coordinate as player and point
cherryRandomX = random.choice(coordX)
cherryRandomY = random.choice(coordY)
for i in range(len(poison)): # regenerate x and y coordinate if cherry shares the same coordinate to other array of poisons
if cherryPoint.getCenter().getX() == poison[i].getCenter().getX() and cherryPoint.getCenter().getY() == poison[i].getCenter().getY():
cherryRandomX = random.choice(coordX)
cherryRandomY = random.choice(coordY)
cherryPoints = False
# poison
if poisonLength % 5 == 0: # generates a poison block each time the player size reaches the multiple of 5
poison[k] = Rectangle(Point(poisonRandomX-pointRadius,poisonRandomY-pointRadius),Point(poisonRandomX+pointRadius,poisonRandomY+pointRadius))
poison[k].setFill("green")
poison[k].setWidth(2)
poison[k].draw(win)
poisonRandomX = random.choice(coordX)
poisonRandomY = random.choice(coordY)
for i in range(len(player)):
if (poison[k].getCenter().getX() == player[i].getCenter().getX() and poison[k].getCenter().getY() == player[i].getCenter().getY()) or (poison[k].getCenter().getX() == point.getCenter().getX() and poison[k].getCenter().getY() == point.getCenter().getY()) or (cherryPoints==True and poison[k].getCenter().getX() == cherryPoint.getCenter().getX() and poison[k].getCenter().getY() == cherryPoint.getCenter().getY()): # regenerate x and y coordinate if they share the same coordinate as player and point and cherry
poisonRandomX = random.choice(coordX)
poisonRandomY = random.choice(coordY)
for i in range(len(poison)):
if poison[k].getCenter().getX() == poison[i].getCenter().getX() and poison[k].getCenter().getY() == poison[i].getCenter().getY(): # regenerate x and y coordinate if new poison shares the same coordinate to other array of poisons
poisonRandomX = random.choice(coordX)
poisonRandomY = random.choice(coordY)
bonus+=50
k+=1
poisonLength+=1
# game over requirements
for i in range(len(poison)): # if player touches poison
if player[0].getCenter().getX() == poison[i].getCenter().getX() and player[0].getCenter().getY() == poison[i].getCenter().getY():
game = False
for i in range(2, len(player)): # if player touches its own body or reach out of window
if (player[0].getCenter().getX() == player[i].getCenter().getX() and player[0].getCenter().getY() == player[i].getCenter().getY()) or x < 0 or x > width or y < 0 or y > gridHeight:
game = False
# FPS
update(10)
countDown += 1
# GAME OVER
gameOver = Text(Point(width/2,200), "GAME OVER")
gameOver.setTextColor("red")
gameOver.setSize(30)
gameOver.draw(win)
update()
time.sleep(2)
win.close()
main()
Ideally the result should replace each code in the while loop with individual classes outside of the function to reduce the amount of lines in the main() function and make the script easier to read.
Classes are essentially just bundles of code that contain various attributes and methods.
A Snake class might have a list of coordinates for each section of the body (the first is the head).
class Snake:
def __init__(self, x, y):
self.positions = [(x, y)]
def get_head(self):
return self.positions[0]
def move_forward(self):
self.positions.pop()
self.positions.insert(0, self.get_head()[1] + 1)
def move_backward(self):
self.positions.pop()
self.positions.insert(0, self.get_head()[1] - 1)
...
And so on. Classes, at this level, let you think of objects as concrete entities, distinct from each other but easily manipulated.
I am building a simple A.I for a "spider game" (pretty much the same concept as the snake game but the moving logic is a bit different). I am trying to implement a BFS algorithm such that the spider finds the path that leads it to the ant. The algorithm seems to work for several iterations but when I run it outside of the debugger it gets a None value inside the node_list and that makes the other methods fail (since you cannot get the next move for anything).
This is the BFS algorithm:
def BFS(spider_state, ant_state):
goal = False
count = 0
initial_node = Node(spider_state, None, 0)
node_list = [initial_node]
initial_ant_state = ant_state
while goal == False or len(node_list) == 0:
e = node_list.pop(0)
future_ant_state = initial_ant_state
for i in range(0, e.depth):
future_ant_state = get_next_ant_move(border_choice, initial_ant_state)
for move in POSSIBLE_MOVES:
count += 1
next_node = Node(None, None, None)
next_node.state = get_next_spider_move(deepcopy(e.state), move)
next_node.parent = e
next_node.depth = e.depth + 1
if next_node.state == future_ant_state:
goal = True
break
else:
node_list.append(next_node)
return node_list
Node:
class Node():
def __init__(self, state, parent, depth):
self.state = state
self.parent = parent
self.depth = depth
Spider and ant are represented as a simple list of x and y positions:
spider = [15, 35]
ant = [20, 10]
The get next move methods look like this:
def get_next_spider_move(spidy, move):
if spidy:
# check the bounds and assign the new value to spidy
spidy = spider_bounds(spidy)
# farthest right
if move == 0:
spidy[1] += 2
spidy[0] -= 1
# furhter up and right
if move == 1:
spidy[1] += 1
spidy[0] -= 2
# backwords
if move == 2:
spidy[0] += 1
# farthest left
if move == 3:
spidy[1] -= 2
spidy[0] -= 1
# furhter up and to the left
if move == 4:
spidy[1] += 1
spidy[0] -= 2
# one left
if move == 5:
spidy[1] -= 1
# one right
if move == 6:
spidy[1] -= 1
# side right
if move == 7:
spidy[1] += 1
spidy[0] += 1
# side left
if move == 8:
spidy[1] -= 1
spidy[0] -= 1
else:
# if no valid direction was given
return spidy
else:
raise ValueError('spidy must contain an x and y position. %s', spidy, ' was found')
The resulting error when run:
File "spider_game_bfs.py", line 141, in <module>
path = BFS(spider, ant)
File "spider_game_bfs.py", line 130, in BFS
next_node.state = get_next_spider_move(deepcopy(e.state), move)
File "spider_game_bfs.py", line 100, in get_next_spider_move
raise ValueError('spidy must contain an x and y position. %s', spidy, ' was found')
ValueError: ('spidy must contain an x and y position. %s', None, ' was found')
You have a logic error at the bottom of your move function. The last complete statement is
if move == 8:
spidy[1] -= 1
spidy[0] -= 1
else:
# if no valid direction was given
return spidy
Your comment is incorrect: the else clause is executed by any move other than 8. If the move is 8, then you return None, as you've skipped the statement that returns spidy.
As the first comment mentioned, you will do better with if ... elif ... else as your logic structure. Even better than that, follow the many on-line examples for moving an item: make a list or dict of the moves, something like this:
move_dir = [
(-1, +2), # move 0
(-2, +1), # move 1
(+1, 0), # move 2
... # fill in the rest
]
if move in range(len(move_dir)):
spidy[0] += move_dir[move[0]]
spidy[1] += move_dir[move[1]]
return spidy
else:
raise ValueError ...
I'm trying to call a class function player.Decide() in another function where it wasn't declared. Im getting the error 'player is not defined. How would I go about fixing this?
def BattleLogic():
global enemy, enemy_race, name, level, strength, dexterity, cunning, enemy_speed, player_speed, type_speed
global move, turn, prefix
if enemy in ['deer']:
enemy_race = 'animal'
if enemy_race == 'animal':
chance = random.randint(1,1000)
if chance <= 10:
prefix = 'crippled'
elif chance > 10 and chance <= 50:
prefix = 'old'
elif chance >50 and chance <= 250:
prefix = 'young'
elif chance > 250 and chance <= 750:
prefix = None
elif chance > 750 and chance <= 950:
prefix = 'strong'
elif chance > 950 and chance <= 990:
prefix = 'alpha'
elif chance > 990 and chance <= 999:
prefix = 'possessed'
elif chance == 1000:
prefix = '*CONVERTED*'
else:
prefix = 'error'
opponent = Enemy(str(prefix),str(enemy),str(enemy_race))
player = Player(str(name),level,strength,dexterity,cunning)
player.Initiative()
opponent.Initiative()
if enemy_speed > player_speed:
move = 0
elif player_speed > enemy_speed:
move = 1
else:
move = random.randint(0,1)
turn = 0
Battle()
def Battle():
global turn, move, prefix, enemy, type_speed, enemy_title
if turn == 0:
print('\n\n')
if prefix == None:
enemy_title = enemy.capitalize()
else:
enemy_title = prefix.capitalize()+' '+enemy.capitalize()
SlowPrint('A '+enemy_title+' gets into position for battle',type_speed,0.5)
if move == 1:
SlowPrint(enemy_title+' makes the first move',type_speed,0.25)
else:
SlowPrint('You make the first move',type_speed,0.25)
if move == 0:
turn += 1
move = 1
player.Decide()
else:
turn += 1
move = 0
opponent.Decide()
Just pass a player object into the function. The you are free to use player.Decide().
The major problems with your coding, which is my personal opinion, is that you do not have the habit of passing something into the function, which as a result forces you to declare too many global variables.
A simple example (in your case, you want the object to be a player)
def Battle(obj):
return obj.Decide()
first time poster here.
Ill try to keep this as simple as possible. I am trying to make a game in pygame but it seems my collision detection is acting up. I have a player class that detects whether or not the player is colliding with the ground or any other objects in the environment list, and I have an enemy class that collides with anything in the same list. The enemies work out what direction they need to travel in in order to try and hit the player. There is gravity which is very likely to play a major part in the problem.
The problem is that when the 'flies' are placed in and fall to the ground, they immediately jump off screen, even though their X and Y values seem (according to logs of items on the screen) to not move at all?
As clarification, the two 'flies' are placed into a secondary list to allow for collision detection. Also, as a side note, the 'glitch' doesn't occur if there is no left and right collide detection... Thanks to anyone who can provide help :)
def collisions():
#Detection Working as intended
for fly in Fly.List:
fly_proj = pygame.sprite.spritecollide(fly, Projectile.List, True)
if len(fly_proj) > 0:
for hit in fly_proj:
fly.health -= 100
X = pygame.sprite.spritecollide(fly, current_level.object_list, False)
if len(X) == 0: #Gravity here:
if (fly.vspeed == 0):
fly.vspeed = 1
print("Gravity")
else:
fly.vspeed += 0.35
if len(X) > 1:
for hit in X:
if fly.vspeed > 0:
fly.rect.bottom = hit.rect.top +1
fly.vspeed = 0
elif fly.vspeed < 0:
fly.rect.top = hit.rect.bottom -1
elif fly.hspeed > 0:
fly.rect.right = hit.rect.left
fly.hspeed = 0
elif fly.hspeed < 0:
fly.rect.left = hit.rect.right
fly.hspeed = 0
print(len(X),framecounter, fly.vspeed, fly.hspeed)
#Kill fly if health reaches 0
if fly.health <= 0:
fly.destroy(Fly)
#Detect where the player is
if window_rect.contains(fly.rect):
fly.playersnapshot = player.rect.x
if fly.rect.x - player.rect.x >= -10:
#print("LEFTING")
fly.hspeed = -2
if fly.rect.x - player.rect.x <= 10:
fly.hspeed = 2
fly.truefalse = True
event = None
fly.rect.y += fly.vspeed
fly.rect.x += fly.hspeed
I think your if/else is incorrect.
Probably when fly touch ground you set vspeed to zero and then if/else checks hspeed and it use ground left/right to change fly left/right.
I know one method.
move fly vertically
check collision and use if/else with vspeed
move fly horizontally
check collision and use if/else with hspeed
--
EDIT:
# move horizontally only
fly.rect.x += fly.hspeed
X = pygame.sprite.spritecollide( ... )
for hit in X:
if fly.hspeed > 0:
fly.rect.right = hit.rect.left
else:
fly.rect.left = hit.rect.right
# move vertically only
fly.rect.y += fly.vspeed
X = pygame.sprite.spritecollide( ... )
for hit in X:
if fly.vspeed > 0:
fly.rect.bottom = hit.rect.top
else:
fly.rect.top = hit.rect.bottom
# on_ground = True
I found this method in source code of "Platform Jumper" on ProgramArcadeGames.com
see page with: platform_jumper.py