How can I solve a maze using stack or queue? - python

I'm using a scribbler robot to navigate a self made maze (which I will improve once I get the functionality working, the one I have in a video is just for testing purposes.)
Maze
I initially was trying to make the robot move left and right solely on the getObstacle sensors. I had trouble tho.. It wouldn't turn left or right as I desired. So I'm thinking of using stack or a queue.
I would like to just tell the robot
if(getObstacle(1) <=6000): # once sensor reaches 6000, it will stop doing the command
forward(1,0) # will move forward as long as getObstacle(1) is less than 6000
Then, once it detects the first obstacle, turn left and go forward
Then once it detects another obstacle, turn right.
I essentially want to map out the left and right turns of the maze and tell the scribbler when to turn beforehand.
So when it senses a wall for the first time = turn left.. then go forward
When it senses a wall for the second time = turn right.. then go forward.
How can I implement this code into a stack or queue?
The code I have now is based purely on the sensors, and it's unreliable.
Here's an example of what I'm working with:
def main():
setIRPower(135)
while True:
left = getObstacle(0)
center = getObstacle(1)
right = getObstacle(2)
# 2 feet per 1 second at 1 speed
if (center <= 6000):
forward(0.5, 0.3)
elif (center >= 6000 and right > left): #if right sensor detects value higher than left
turnLeft(1, .55) #left turn
else:
turnRight(1, .55) #otherwise, turn right
I'm working with different variations of the code above. I just would like to implement the turns in a queue or stack, and I'm not sure how to do it.
Thanks

Related

Python Turtle - Issue with custom shape in Snake program

I have a python program using turtle to make the game "Snake". It is fully functional. At this point I'm adding in .gif images to spruce it up.
The problem arises when I'm trying to use a custom shape as the head of the snake. If I use a basic shape from turtle like "triangle" or "arrow" it works fine. It turns correctly and is printed over the first body segment as intended. When I change it to my custom image, the problem is that it is printed out under the first body segment and cannot turn.
Sample of controls
if direction == "up":
if snake_direction != "down":
snake_direction = "up"
head_stamper.setheading(90)
Stampers used to make numerous sections, and a head over the first segment.
for segment in snake:
stamper.goto(segment[0], segment[1]) #These are the body segments, they work fine.
stamper.stamp()
head_stamper.goto(new_head)
Showing both stampers here.
# Stamper for each body section
stamper = turtle.Turtle()
stamper.shape(bod_segment)
stamper.shapesize(25 / 20)
stamper.penup()
# Special stamper just for the snake's head.
head_stamper = turtle.Turtle()
# head_stamper has no issues when I make the shape "arrow" or "triangle", etc.
head_stamper.shape(head_segment)
stamper.shapesize(25 / 20)
head_stamper.penup()
I think this is all the code relevant to the problem.
When I change it to my custom image, the problem is that it is printed
out under the first body segment and cannot turn.
As far as not turning, this is addressed in the Python turtle documentation of register_shape() aka addshape():
Note: Image shapes do not rotate when turning the turtle, so they do
not display the heading of the turtle!
As far as the overlap problem, I can only guess. Generally the rule in turtle is the last thing that moved is on top. So turning your generic head shape lands it on top, but since your image shape doesn't actually turn, it winds up on the bottom. Again, just a guess.

psychopy event based on mouse position

I am setting up a Fitts' law experiment where I would like a participant to click on a start button, move the mouse in a straight line, and then click on a target. After clicking start, if the participant moves their mouse too far up or down in the vertical direction I would like to display a white screen for 30 seconds and accept no input, afterward moving to the next trial.
Currently, no matter what, the experiment is behaving as if I'm moving outside the acceptable range and always executes the if statement.
Here is the code for it that I have right now:
from psychopy import core
start = mouse.isPressedIn(polygon, buttons=[0])
if start==True:
thisExp.addData('starttime',core.getTime())
x, y = mouse.getPos()
mouse.x.append(x)
mouse.y.append(y)
if y>10 or y<-10: #this is the statement that isn't resulting in what I would expect
thisExp.addData('penalty',1)
finish = mouse.isPressedIn(polygon2, buttons=[0])
if finish==True:
thisExp.addData('stoptime',core.getTime())
continueRoutine=False
I haven't figured out everything I need under the nested if statement yet. Right now I am just trying to make sure it works correctly. It never evaluates the if statement as true and never adds the penalty, even though looking at the collected mouse.y list data in the csv file I can see that there were instances where y was outside of whatever range I set.
It appears that mouse position data is being collected as soon as the trial begins, not just after polygon is clicked. However, starttime and stoptime do appear to be based on when polygon and polygon2 are clicked. I'm really not sure what is going on.
UPDATE:
I didn't get notified about Jonas' response until a day later for some reason. I wish I had because it would have put me on the right track a few hours earlier. It's a builder code component.
My code was all running each frame. At the beginning of the routine I added:
checkstart = False
That with the following code each frame solves this particular problem:
start = mouse.isPressedIn(polygon, buttons=[0])
if start==True:
thisExp.addData('starttime',core.getTime())
x, y = mouse.getPos()
mouse.x.append(x)
mouse.y.append(y)
checkstart=True;
if checkstart==True:
if y>10 or y <-10:
thisExp.addData('penalty',1)
finish = mouse.isPressedIn(polygon2, buttons=[0])
if finish==True:
thisExp.addData('stoptime',core.getTime())
continueRoutine=False
I still don't know why mouse position is collected before polygon is clicked but it doesn't actually matter to me. I can match the data for the frame where the mouse was clicked to the position that corresponds to the start button to get the beginning of the mouse path trace.
My code was all running each frame. At the beginning of the routine I added:
checkstart = False
That with the following code each frame solves this particular problem:
start = mouse.isPressedIn(polygon, buttons=[0])
if start==True:
thisExp.addData('starttime',core.getTime())
x, y = mouse.getPos()
mouse.x.append(x)
mouse.y.append(y)
checkstart=True;
if checkstart==True:
if y>10 or y <-10:
thisExp.addData('penalty',1)
finish = mouse.isPressedIn(polygon2, buttons=[0])
if finish==True:
thisExp.addData('stoptime',core.getTime())
continueRoutine=False
I still don't know why mouse position is collected before polygon is clicked but it doesn't actually matter to me. I can match the data for the frame where the mouse was clicked to the position that corresponds to the start button to get the beginning of the mouse path trace.

How to make a shot impact in a rectangle only output one event?

In pygame, I am trying to make my points increase by 1000 every time a shot impacts my zombie, who's positions are zhot[XX] and zhot[YY]. I attempted to accomplish this by creating a rectangle around my zombie, and using the collidepoint function, however as my shot passes through the rectangle, every change in it's position counts as 1000 points, so shooting one zombie will give me something like 30000 points. How can I fix this?
for shot in shots:
zomrect2=Rect(zhot[XX],zhot[YY],49,38)
if zomrect2.collidepoint(shot[X],shot[Y]):
points+=1000
Once you've awarded points, you need to break out of the for loop.
for shot in shots:
zomrect2=Rect(zhot[XX],zhot[YY],49,38)
if zomrect2.collidepoint(shot[X],shot[Y]):
points+=1000
break #no more points will be awarded, there's no point wasting computation checking the rest.
I guess the loop you posted runs inside your main loop and is invoked every iteration of the main loop.
You should remove the shot from the shots list once it hit your zombie, so it won't be checked again for collision in the next iteration of the main loop.
zomrect2=Rect(zhot[XX],zhot[YY],49,38)
# make a copy of the list so we can savely remove items
# from it while iterating over the list
for shot in shots[:]:
if zomrect2.collidepoint(shot[X],shot[Y]):
points += 1000
shots.remove(shot)
# and also do whatever you have to do to
# erase the shot objects from your game
You need to track the fact that the points have been awarded already. It's not really clear how/when the method or function awarding points is being called, but something like this perhaps:
points_awarded = False
for shot in shots:
zomrect2=Rect(zhot[XX],zhot[YY],49,38)
if zomrect2.collidepoint(shot[X],shot[Y]) and not points_awarded:
points_awarded = True
points+=1000

top down friction in pymunk

Been struggling with this for a couple of days, hard to find code examples on the net.
I'm making a topdown game and having trouble getting the player to move on key press. At the moment i'm using add_force or add_impulse to move the player in a direction, but the player doesn't stop.
I've read about using surface friction between the space and the player to simulate friction and here is how it's done in the tank.c demo.
However I don't understand the API enough to port this code from chipmunk into pymunk.
cpConstraint *pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(tankControlBody, tankBody, cpvzero, cpvzero));
So far, I have something that looks like this:
class Player(PhysicalObject):
BASE_SPEED = 5
VISIBLE_RANGE = 400
def __init__(self, image, position, world, movementType=None):
PhysicalObject.__init__(self, image, position, world)
self.mass = 100
self.CreateBody()
self.controlBody = pymunk.Body(pymunk.inf, pymunk.inf)
self.joint = pymunk.PivotJoint(self.body, self.controlBody, (0,0))
self.joint.max_force = 100
self.joint.bias_coef = 0
world.space.add(self.joint)
I don't know how to add the constraint of the space/player to the space.
(Need someone with 1500+ rep to create a pymunk tag for this question).
Joe crossposted the question to the Chipmunk/pymunk forum, and it got a couple of more answers there. http://www.slembcke.net/forums/viewtopic.php?f=1&t=1450&start=0&st=0&sk=t&sd=a
Ive pasted/edited in parts of my answer from the forum below:
#As pymunk is python and not C, the constructor to PivotJoint is defined as
def __init__(self, a, b, *args):
pass
#and the straight conversion from c to python is
pivot1 = PivotJoint(tankControlBody, tankBody, Vec2d.zero(), Vec2d.zero())
# but ofc it works equally well with 0 tuples instead of the zero() methods:
pivot2 = PivotJoint(tankControlBody, tankBody, (0,0), (0,0))
mySpace.add(pivot1, pivot2)
Depending on if you send in one or two arguments to args, it will either use the cpPivotJointNew or cpPivotJointNew2 method in the C interface to create the joint. The difference between these two methods is that cpPivotJointNew want one pivot point as argument, and the cpPivotJointNew2 want two anchor points. So, if you send in one Vec2d pymunk will use cpPivotJointNew, but if you send in two Vec2d it will use cpPivotJointNew2.
Full PivotJoint constructor documentation is here: PivotJoint constructor docs
I'm not familiar with either system you've mentioned, but some basic game ideas that may relate are:
If you add a force (or impulse) which affects movement, for the entity to stop, you must also take it away. In my games if I had a function AddImpulse()/AddForce() I would have a corresponding one such as Apply_Friction() which would reverse the effect by however much you want (based on terrain?) until movespeed is zero or less. I personally wouldn't bother with this method for movement unless needed for gameplay since it can add more computations that its worth each update.
There should be some way to track KeyPressed and/or KeyPosition and then using those x/y coordinates are incrememnted based on player speed. Without knowing what you've tried or how much the API does for you, it's hard to really say more.
Hope this helps. If this is stuff you already knew kindly ignore it.

Pygame: Sprite animation Theory - Need Feedback

After some tweaking of some code I got from someone to cause a characters images to move in regards to its direction and up down left right input I've put this together: (hope the code isn't too messy)
Character Move Code + IMG
The Sprite sheet only runs lengthwise, so basically each sprite section is a different action. Now would there be a way I could make a code that functions with the current one to cycle down from a set 'action' in order to make an animation?
For example:
'Run Left' is sprite 3. So then after we designate that column would it be possible to loop down how ever many frames of the run animation (lets say 4) in order to make an animation?
Example Picture:
http://animania1.ca/ShowFriends/dev/example.jpg
It should be easy.
If you record the frame number in a variable, you can modulo this with the number of frames you have to get an animation frame number to display.
frame_count = 0
animation_frames = 4
while quit == False:
# ...
# snip
# ...
area = pygame.Rect(
image_number * 100,
(frame_count % animation_frames) * 150,
100,
150
)
display.blit(sprite, sprite_pos, area)
pygame.display.flip()
frame_count += 1
If different actions have different numbers of frames, you'll have to update animation_frames when you update image_number.
Also, this assumes that it's ok to play the animation starting at any frame. If this is not the case, you'll need to record what the frame count was when the action started, and take this away from frame count before the modulo:
area = pygame.Rect(
image_number * 100,
((frame_count - action_start_frame) % animation_frames) * 150,
100,
150
)
A note about your event handling. If you hold down, say, left, and tap right but keep holding down left, the sprite stops moving because the last event you processed was a keyup event, despite the fact that I'm still holding left.
If this is not what you want, you can get around it by either keeping a record of the up/down states of the keys you are interested in, or by using the pygame.key.get_pressed interface.
On another note, you appear to be aiming for a fixed frame rate, and at the same time determining how far to move your sprite based on the time taken in the last frame. In my opinion, this probably isn't ideal.
2D action games generally need to work in a predictable manner. If some CPU heavy process starts in the background on your computer and causes your game to no longer be able to churn out 60 frames a second, it's probably preferable for it to slow down, rather then have your objects start skipping huge distances between frames. Imagine if this happened in a 2D action game like Metal Slug where you're having to jump around avoiding bullets?
This also makes any physics calculations much simpler. You'll have to make a judgement call based on what type of game it is.

Categories