I have been working on this game, but I have a question when it comes to collision detection. Can I check for collision and have it return True:
example:
def collide(self, EnemyTank):
tank_collision = pygame.sprite.collide_rect(self.rect, EnemyTank.rect)
if tank_collision == True:
return True
And then make it perform an action like this:
if player.collide == True:
e_tank_x += 0
I am new to programming so please bear with me, I am trying as hard as I can and any comments or suggestions would also be very appreciated.
I'm not an expert of pygame, but it sound perfectly legitimate. I would just take away the middle man in your initial function:
def collide(self, EnemyTank):
return pygame.sprite.collide_rect(self.rect, EnemyTank.rect)
And you need to adjust the test you use, as you want to actually check the collision, while as you wrote it it just test if the function collide exist ;)
You can also use the implicit testing, removing some unnecessary character (best abith are best learned early)
if player.collide(EnemyTank):
do your action here
good luck with your game!
Related
I'm starting out with python, I only know the basics and I want to create a top-down type of game to the one I have currently.
I've tried some solutions on the internet and sadly, none of them has worked for me.
As I said, I can't find a working solution as of right now but I've tried a few, including this one
How can I make the player “look” to the mouse direction? (Pygame / 2D).
I'm also using pygame, forgot to mention that. I also have pgzero if you need to know.
This code works and it just places a new actor when you click on it, but I want to have a type of 'character' with a weapon that can move around and 'look' at the mouse.
import pgzrun
from random import randint
apple = Actor("apple")
score = 0
def draw():
screen.clear()
apple.draw()
def place_apple():
apple.x = randint(10, 800)
apple.y = randint(10, 600)
def on_mouse_down(pos):
global score
if apple.collidepoint(pos):
print("Good Shot!")
place_apple()
score = score + 1
print(score)
else:
print("You Missed!")
quit()
pgzrun.go()
I just need to know how to make the picture 'look' at the cursor and then what each bit does to I know hot to do it for next time.
The first time I tried with the link given above, It returned a positional argument and I can't figure it out.
I may have messed something up when I put in the fixed code but I don't know, I was kind of tired.
I am not sure what exactly you mean with "aim at the mouse" but I guess you want to change the drawn image according to some program logic.
You do this simply setting the image property of the Actor to another picture, eg. when you click on the image, see my modified version of your
def on_mouse_down(pos):
global score
if apple.collidepoint(pos):
print("Good Shot!")
place_apple()
score = score + 1
apple.image = "cactus" # ADDED: Change the image if your click hit the Actor
print(score)
else:
print("You Missed!")
quit()
You can find the documentation of the complete API (function calls and properties) here:
https://pygame-zero.readthedocs.io/en/stable/builtins.html
I'm making my own game with Python2.7 through the pygame libraby.
It's a 1v1 combat game where players use the same keyboard.
The game works in a main loop that is repeated 60times per second, every time the loop is executed, it calculates lots of things e.g the position, problem is that I have 2 players, so I have to write the lines two times.
Example here:
if p1direction == 'right' and p1XS < p1Attributes[1]: p1XS +=
p1Attributes[0]
and:
if p2direction == 'right' and p2XS < p2Attributes[1]: p2XS +=
p2Attributes[0]
See the differences p1 and p2, they are variables that belongs to Player 1 and Player 2 respectively.
I just want to find a solution to not write every time the same lines just for p2. I was thinking about the for function so I can even add players easly but I don't know how to do it in this case...
Can someone help me ? :) Please
Create a class player.
Then add the attributes of each player to the class.
Instantiate your class with player 1 and 2.
class Player():
direction = "right"
etc.
def shoot(self):
if self.direction == "right"
shoot_right()
playerOne = Player()
playerTwo = Player()
direction = playerOne.direction
If you haven't used classes yet, I wouldn't recommend using them though. Inheritance can get pretty nasty...
Hope that helped,
Narusan
EDIT:
If you haven't used classes in Python yet, I recommend catching up there first and then continuing your game development. I have programmed several games in pygame as well, and classes come in very hand. In fact, it is almost impossible to create pygame games without using proper classes (or endless if-clauses and for-loops that will make everything super slow).
Wish you all the best of luck
How about storing your variables(for example p1direction and p2direction) in a vector(player_directions) indexed by the player number and using a loop access it, for example:
number_of_players = 2
playersXS = function_that_fills_playersXS() # return a vector containing your p1XS and p2XS variables in a vector
for player_number in xrange(number_of_players):
if player_directions[player_number]=='right' and playersXS[player_number]< Attributes[player_number][1]:
playersXS[player_number]+=Attributes[player_number][0]
I'm trying to create some obstacles for the player in my program. I can't figure out how to make the sprite stop when it comes in contact with it from all sides.
I tried to use pygame.sprite.collide_rect and pygame.sprite.spritecollide, but couldn't figure out how to do it.
If you could just try to explain the concept, I'd rather try to figure the rest out myself. Thanks in advance!
def move_rect():
new_pos = player_rect.pos
new_pos = new_pos[0]+dx,new_pos[1]+dy
new_rect = rect(new_pos,player_rect.size)
for enemy in enemy_rects:
if new_rect.colliderect(enemy):
dx,dy=dx*-1,dy*-1 #reverse direction to "bounce"
#alternatively you could just return here probably
player_rect.move(dx,dy) #do the move, no collisions
something like that at least ... (I doubt it will work, its more to give you the concept)
I am using python and pyglet in a 2d game but I have come across a problem in collision detection. My code to check for collision looks like this:
def distance(self,target):
return math.sqrt((self.x-target.x)**2 + (self.y-target.y)**2)
def check_collision(self):
for i in list_of_mobs:
if self.distance(i) < (self.width/2 + i.width/2):
return True
It checks the distance from each sprite with "target" being another sprite. The thing I am unsure of is "should I be checking for collisions between all the sprites?" I have over 200 mobs (even more I hope in the finished product) and it becomes unplayable when the collisions are checked. Is there someway to only check sprites within a certain distance without losing speed?
EDIT:
I had a read around google and found out that a lot of the speed was spent doing the same collisions. i.e. sprite1 was checked with sprite2 and sprite2 was checked with sprite1. So I made a few changes to the check collision function and it runs quicker now but still less than 20 fps
def check_collision(self):
global mobs_to_collide
if mobs_to_collide == []:
mobs_to_collide = list_of_mobs[:]
if self in mobs_to_collide:
mobs_to_collide.remove(self)
for i in mobs_to_collide:
if self.distance(i) < (self.width/2 + i.width/2):
return True
(it may contain some inefficient code/useless stuff. I was playing around with it a bit)
EDIT2:
I decided to use rabbyt as the sprite library. The collisions are fast and easy. I replaced the code above ^^ with:
rabbyt.collisions.collide(mobs_to_collide)
This returns a list of lists (I'm not sure if that's the correct term) with the objects that collided. I'm still working on how to translate that into an "if collided:" type statement but I am making progress. If anyone is in a similar situation, I would reccomend using rabbyt.
A simple way to improve the speed on this, could be to remove the square root operation.
def distancesq(self,target):
return (self.x-target.x)**2 + (self.y-target.y)**2
def check_collision(self):
for i in list_of_mobs:
# Square this distance to compensate
if self.distancesq(i) < (self.width/2 + i.width/2)**2:
return True
Probably it is already too late, but I had exactly the same problem. I managed to solve it by calculating collisions only for visible objects, like that:
for object_ in objects:
if not object_.visible: # pyglet.sprite.Sprite() provides this flag
continue
# rest of your collision detection
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.