i am making a game and i need to be able to sense if a character is touching a tree or not and i can't because the tree is part of the background.
i've already tried using x and y co-ordinates but the trees aren't in a specific clump so this doesn't work. i also tried using a piece of code - look below - that detects if something is touching something else, however, the thing has to be defined and i can't define the tree.
def tree():
tree = #brown
if sprite_x < 0 + sprite_width and sprite_x + tree_width > 0 and sprite_y < 0 + sprite_height and sprite_height + sprite_y > tree_height :
#do stuff
i expect the code to sense if the character is touching a brown colour (the tree) and to allow me to use that output.
Related
So, i'm doing little game with python and pyglet, but i'm stuck with moving the object in xy axis.
I have object A which is dictionary, it has x-coordinate, y-coordinate and speedvectors for x and y.
When i launch this object A it flies like it should, the problem is i'm moving it like this.
objectA["y"] = objectA.get("y") + objectA.get("ySpeed")
objectA["x"] = objectA.get("x") + objectA.get("xSpeed")
So the coordinates are moving rapidly like first objextA x is 130 then its 160 etc. When i'm trying to do some collision things, object wont stop because it doesn't register hit, it skips over the block (or atleast i think it does so). Any tips how i should actually do this?
Your code is correct. I tested it in an empty script and it worked fine
Try this in a empty script and look at the results. It should first print 0 and then print 10:
objectA = {"x": 0, "y": 0, "xSpeed": 1, "ySpeed": 1}
print(objectA["x"])
for _ in range(10):
objectA["x"] = objectA.get("x") + objectA.get("xSpeed")
print(objectA["x"])
It might be something else in your code that causes the problem.
Btw, this is a shorter way of writing your posted code (it does exactly the same):
objectA["x"] += objectA["xSpeed"]
objectA["y"] += objectA["ySpeed"]
For my project in AH Computing I'm recreating my version of Nidhogg. Everything runs smoothly until the blood starts spraying. Im not too sure how i can make the code more efficient as i am still fairly new to python.
This is the class for the the spraying blood:
class bloodmaker():
def __init__(self,xv,yv,colour,x,y):
self.gravity = 2
self.air_resistance = 0.25
self.xv = xv
self.yv = yv
self.x = x
self.y = y
self.pastx = 0
self.pasty = 0
self.colour = colour
def move(self):
if self.y < 400:
self.pastx = self.x
self.pasty = self.y
#so that it doesnt curve backwards
if self.xv > 0:
self.xv -= self.air_resistance
self.yv += self.gravity
self.x += self.xv
self.y += self.yv
#so that the drawn line doesnt go over the edge
if self.y > 400:
self.y = 400
if self.colour is "o":
py.draw.line(screen, (255, 165, 0), (self.pastx-backgroundx, self.pasty), (self.x-backgroundx, self.y),5)
else:
py.draw.line(screen, (255, 255, 0), (self.pastx-backgroundx, self.pasty), (self.x-backgroundx, self.y),5)
else:
global bloodgrid
try:
#the bloodgrid are squares 5 pixels wide, covering the bottom section, so we we divide by 5 to find where to put the blood
bloodgrid[int(self.x/5)].insert(0,self.colour)
except:
pass
#deleting this object as it is no longer required
return True
[Here is an image of the blood spraying][1]
(excuse the incomplete sprite)
[1]: https://i.stack.imgur.com/hXiAa.png
Underneath there is a floor of blood that works using an array of stacks, which is added above code when it the blood reaches the floor.
bloodgrid = [[] for x in range(512)]
Here is the code for destroying the flying blood object and blitzing the blood floor to the screen.
def blood():
for i in range(len(bloodarray)):
killyourself = bloodarray[i].move()
if killyourself is True:
kill.append(i)
#appends to a kill list as if i popped here the list would get shorter while the for loop stays the same giving an out of index error
for i in range(len(kill)):
bloodarray.pop(kill[0]-i)
kill.pop(0)
#printing the entire bloodgrid
for i in range(512):
for ii in range(len(bloodgrid[i])):
try:
if bloodgrid[i][ii] is "o":
py.draw.rect(screen, (255, 165, 0), ((i*5)-backgroundx, ii*5+400, 5, 5))
else:
py.draw.rect(screen, (255, 255, 0), ((i*5)-backgroundx, ii*5+400, 5, 5))
except:
pass
I don't think it is possible to only update parts of the screen as the camera moves about and the blood on the floor moves too.
As more blood accumulates on the floor the game framerate starts to drop and it gets especially choppy when the blood sprays. Is there any ways I could make this more efficient? I don't want to hand in a choppy game but I really like how the blood looks. Thanks.
A couple of points that are hopefully helpful.
(This isn't directly related to speeding up your code, but...) Try to get away from using global variables. Just pass them into your functions. Several of the ones you posted are difficult to figure out because you are accessing variables that are outside the scope of the function.
First reason things are bogging down here: You are using insert() to insert new elements at the start of a list, and you are doing that inside of a loop where you call the move() function. Inserting anywhere into a list (except the end) is horribly slow for reasons beyond the scope of this post. You should consider putting a deque from collections in there, which can be inserted front or back efficiently. If that is daunting, you could also "do a little math" and insert at the end of your list and draw it backwards by counting down from the last element, which is also efficient.
Also in the same notion, as mentioned in the comments, poping things out of the middle of lists or arrays is also horribly slow. Figure out a different way or look at a different data structure. It is tough to give advice on this point because bloodarray is not defined in your code.
Basically: things are bogging down because you are choosing the wrong data structures. tweak a couple of them and you'll get better results.
This question already has an answer here:
How do I get the snake to grow and chain the movement of the snake's body?
(1 answer)
Closed 1 year ago.
ok so i have been playing around with pygame and python and I have already build snake but that was a very weird system and i want to build like a pathfinder for it that can path find around obstacles (the snake body) to the apple but the movement of the body is wonky and i know that sounds stupid since i cant even make snake how am I gonna make a pathfinder but i have done it before so here goes:
the snake will look like this: snake = [[1,0],[0,0]]
the direction is just stored in a tuple: direction = (xmov = 1,ymov = 0)
time += 1
if time > 30:
time = 0
snakeindex = len(snake)-1
snakeindex will be one
while snakeindex > 0:
this activates once and as far as it know it works
snake[snakeindex] = snake[snakeindex-1]
snakeindex -= 1
the snake will end up like this: [[1,0],[1,0]]
but then here:
snake[0][0] += direction[0]
snake[0][1] += direction[1]
the snake will then look like this: [[2,0],[2,0]]
Python optimization is messy sometimes for mutable objects like lists,dictionaries etc. Your snake parts is just one part, and references to this part.
You shouldn't do thing like:
a = [1,2]
b = a
# Now you might think there's to arrays
# But it's one array, and b is just a reference to a.
# If you change b or a both changes.
a[0] = 9
print(a, b)
# This will print out [9,2] and [9,2]
Use .copy() to actually copy list:
snake[snakeindex] = snake[snakeindex-1].copy()
I'm making a variation of the "Snake" game. Segments1 is a list containg the snake's body parts
This piece of code works fine in making the first part of the body follow the head
if len(segments1) > 0:
x = player1.xcor()
y = player1.ycor()
segments1[0].goto(x,y)
But the rest of my code, which is supposed to make the other body parts follow the first body part, just stacks the body parts on top each other
for index in range(len(segments1)):
if index > 0:
x = segments1[index-1].xcor()
y = segments1[index-1].ycor()
segments1[index].goto(x,y)
Image shows snake after eating two pieces of food, black being the head, one grey body part a little behind it and another grey body part stacked on top
You have the wrong algorithm. Since each body part follows the one in front, then the net effect is to simply make the end segment go away.
segments[-1].del
The concept is that each segment is set the to prior segment's location. I guess the assumption is that player1 is the head, but conceptually the head could also be the "first" segment and in that case prior_position would be set to where ever the head was expected next.
prior_position = (player1.xcor(), player1.ycor())
for segment in segments1:
current_position = (segment.xcor(), segment.ycor())
segment.goto(**prior_position)
prior_position = current_position
So I have been fooling around with Pygame and have run into a problem that I can solve, but only in-elegantly.
Basically I have a unit(at this point just a red square) on a plain field of black. If I click the Unit and then click anywhere else on the field the unit proceeds to that point. The algorithm itself works pretty flawlessly, even once obstacles are introduced it handles path-finding quickly.
My problem is in my implementation. The unit is a 16 by 16 square, the field is thus divided into 16 by 16 squares. If I change the unit's destination while it is in transit it sometimes "back-tracks" to the previous "way-point" before continuing on its new route.
I understand why this happens, The path finding module treats each square as a point on a grid, so that the pixel coordinate of point (2,2) is actually (32,32), when I pass the mouse coordinates into the path method I divide them by 16 getting rounded down integers(so (34,37) becomes (2,2)) so while the unit may be between actual "grid-points" the path finding module finds the path from its last actual way point, not it's current location. when it passes the new route to the unit, the unit has to "back-track" in order to follow the route the path-finding module has found
clearly every game developer that does any kind of path-finding has solved this so I'm hoping that I can find a more elegant solution.
I don't want to find a path along every single pixel on the screen just waypoints, but the backtracking is a little irritating. Any suggestions?
as suggested below is the concerned code:
in the main .py file
if pygame.mouse.get_pressed()[0]: # if left mouse button pressed
mouse_x,mouse_y = pygame.mouse.get_pos()
if selected: # checks if a unit is selected
unit.getRoute((mouse_x/16,mouse_y/16))
in the unit.py file
def getRoute(self,target):
self.route = path((self.x/16,self.y/16), target)
def getNode(self):
if self.route:
self.node = route.pop(0)
dif_x,dif_y = self.node[0] - self.x, self.node[1] - self.y
if dif_x > 0:
self.vector_x = self.speed
if dif_x < 0:
self.vector_x = self.speed * -1
else:
self.vector_x = 0
if dif_y > 0:
self.vector_y = self.speed
if dif_x < 0:
self.vector_y = self.speed * -1
else:
self.vector_y = 0
else:
self.node = None
self.vector_x = 0
self.vector_y = 0
def update(self):
if self.route or self.node:
if self.route and not self.node:
self.getNode()
if (self.x,self.y) == self.node:
self.getNode()
self.x += self.vector_x
self.y += self.vector_y
self.rect.topleft = (self.x,self.y)
You should take care of managing this first step in a special way. This because even if the unit is already moving the cell specified with it remains the same until it reaches the next one.
Now I suggest you to make sure to update the cell of the unit as soon as half of the movement has been done (so that the pathfinder will search for the path from the next cell and not from the previous one). In addition you should manage the special situation with something like
if unit is standing still
compute pathfinding as you would normally do
else
compute pathfinding from the unit cell
discard the first cell of the pathfinding route (since it would backtrack)
compute the route directly to the next cell (by drawing a correct path)
Of course this will be easier or harder according to how much freedom of movement you have, if you allow only orthogonal movements that it will be straightforward, if you allow diagonal movement then you should make care to not cross over an obstacle (then it depends on how much tolerance you want to small glitches, like the unit overlapping with a corner of an obstacle).