cant move the character at the same time the obstacle is moving, pirincipal is the name of the image that works as the player
def move():
def left(event):
x = -5
y = 0
canvasGame.update()
edgeReached()
canvasGame.move(principal,x, y)
collision()
def right(event):
x = 5
y = 0
canvasGame.update()
edgeReached()
canvasGame.move(principal,x, y)
collision()
canvasGame.bind_all("<Left>", left)
canvasGame.bind_all("<Right>", right
move()
class Barrel:
def __init__(self, canvas):
self.canvas = canvas
self.obs = canvasGame.create_image(125, 500, image=nuevoObs, anchor=tk.NW)
self.x = 16
self.y = 0
def movement(self):
while True:
coords = canvasGame.coords(self.obs)
if (coords[0] >= 1000):
self.x = -10
self.y = 0
elif (coords[0] < 0):
self.x = 10
self.y = 0
self.canvas.move(self.obs, self.x,self.y)
canvasGame.update()
time.sleep(0.05)
def createBarrel():
barrel = Barrel(canvasGame)
circle_thread = Thread(target=barrel.movement())
circle_thread.daemon = True
circle_thread.start()
createBarrel()
def plzmove():
moveplz = Thread(target=move())
moveplz.daemon = True
moveplz.start()
plzmove()
I tried creating threads but the problem continues, if there is a barrel moving, the player cant move (if there is nothing else moving, the player can move with freedom), also, the player movement is just an image being moved, any tip is appreciated, much love.
I am new to programming and started with pygame zero. I am making a little game where you shoot a rocket to an alien. But my rocket keeps stuck to the border when fired, I made a reload function but I want it to go automatically ( when it hits the border or alien to go back to its normal position). Can anyone help me with that?
alien = Actor('alien', (100,100))
ship =Actor('ship', (500,400))
rocket_fire = Actor('rocket_fire', (500,400))
WIDTH = 1000
HEIGHT =500
def draw():
screen.clear()
screen.blit('space_back', (0,0))
rocket_fire.draw()
ship.draw()
alien.draw()
def move_ship(ship):
if keyboard.left:
ship.x -= 3
rocket_fire.x -= 3
elif keyboard.right:
ship.x += 3
rocket_fire.x += 3
elif keyboard.space:
animate(rocket_fire, pos = (ship.x,0))
elif keyboard.r:
rocket_fire.pos = (ship.x,ship.y)
def move_alien(alien):
alien.right +=2
if alien.left > WIDTH:
alien.right = 0
collide = rocket_fire.colliderect(alien)
if collide == 0:
alien.image = 'alien'
elif collide == 1:
alien.image = 'nuclear_explosion'
def update():
rocket_fire.draw()
ship.draw()
alien.draw()
move_ship(ship)
move_alien(alien)
You can try to assign the initial values to 'rocket_fire' after 'collide == 1'.
elif collide == 1:
alien.image = 'nuclear_explosion'
// rocket_fire = (500,400) -> this is just a representation to assign position; not accurate as per the code
import pygame
import sys
from pygame.sprite import Sprite
class Settings:
def __init__(self):
self.raindrop_speed = 3
self.raindrop_direction = -1
self.raindrop_dropseed = 3
self.backgroundcolor = (30,30,30)
class Drop(Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("raindrop.png")
self.rect = self.image.get_rect()
self.rect.y = self.rect.height
self.rect.x = self.rect.width
self.x_cord = self.rect.x
self.y_cord = self.rect.y
class RainDrop:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((1200,800))
self.settings = Settings()
self.backgroundcolor = self.settings.backgroundcolor
self.raindrops = pygame.sprite.Group()
self.screen_rect = self.screen.get_rect()
self._add_raindrops()
def _add_raindrops(self):
new_raindrop = Drop()
drop_height = new_raindrop.rect.height
drop_width = new_raindrop.rect.width
print(drop_width)
screen_space = self.screen_rect.width
screen_height_space = self.screen_rect.height
aviable_row_space = screen_height_space//(drop_height*2)
avivable_screen_space = screen_space - (drop_width*2)
amount_of_columns = avivable_screen_space//(drop_width*2)
self._add_columns(amount_of_columns,aviable_row_space)
def _add_columns(self,amount_of_columns,aviable_row_space):
for height_of_drops in range(aviable_row_space):
for number_of_drops in range(amount_of_columns):
drop = Drop()
drop.x_cord = (drop.rect.width *2)* number_of_drops
drop.y_cord =(drop.rect.height *2)* height_of_drops
drop.rect.x = drop.x_cord
drop.rect.y = drop.y_cord
self.raindrops.add(drop)
def _bring_down_raindrops(self):
for drop in self.raindrops:
drop.y_cord += self.settings.raindrop_dropseed
drop.rect.y = drop.y_cord
def _update_drops(self):
height_counter = 1
self.raindrops.update()
for drop in self.raindrops.copy():
drop.x_cord += self.settings.raindrop_direction * self.settings.raindrop_speed
drop.rect.x = drop.x_cord
if drop.rect.right >= self.screen_rect.right:
self.settings.raindrop_direction = -1
self._bring_down_raindrops()
elif drop.rect.left <= 0:
self.settings.raindrop_direction = 1
self._bring_down_raindrops()
#if drop.rect.y >= self.screen_rect.height or drop.rect.y <= 0:
# drop.rect.x = drop.rect.width
# drop.y_cord = drop.rect.height
# drop.rect.y = drop.y_cord
print(height_counter)
print(self.raindrops)
def _update_game(self):
self.screen.fill(self.backgroundcolor)
self.raindrops.draw(self.screen)
pygame.display.flip()
def _check_events(self):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
sys.exit()
def run_game(self):
while True:
self._check_events()
self._update_drops()
self._update_game()
if __name__ == "__main__":
rd = RainDrop()
rd.run_game()
Everytime I run this program the rectangle(waterdrops) when they reach the end of the screen a bigger gap appears I have looked at the code for several hours and I can not see what the problem is, I think it has to do with the condition in bottom but I am not sure I have messed with it and changed some values but it still does the same thing.
Your problem is in what you do when you recognize that you've hit the edge of the screen. You do this when you find any drop that has gone off of the screen, and at that point, you reverse direction. The problem is, you've already moved some of the drops on the top row in one direction, but after you recognize the edge of the screen, you then go on to move the rest of the drops in the opposite direction in that same pass. This is how things get out of wack.
What you want to do is note that you've hit the edge of the screen, but not do anything differently right away, so that you still deal with all of the drops on the screen the same way in that pass. After you've drawn all of the drops, you then change direction.
Here's a version of _update_drops that will do this:
def _update_drops(self):
height_counter = 1
self.raindrops.update()
# assume we haven't hit either edge of the screen
reverse = 0
for drop in self.raindrops.copy():
drop.x_cord += self.settings.raindrop_direction * self.settings.raindrop_speed
drop.rect.x = drop.x_cord
if drop.rect.right >= self.screen_rect.right:
# remember that we hit the right edge of the screen
reverse = -1
elif drop.rect.left <= 0:
# remember that we hit the left edge of the screen
reverse = 1
# if we hit one of the edges, change directions and drop down
if reverse != 0:
self.settings.raindrop_direction = reverse
self._bring_down_raindrops()
I'm working on a tic tac toe game in processing.
I can't figure out how to make a way to have X and O swap to vaguely imitate swapping turns I have seen someone did it like the code below but for some reason, I either get an error or it just doesn't work when I hook it up to my preexisting code.
I should have Elaborated more I plan (attempt) to use the Minimax algorithm to make this game unwinnable
print("Begin")
global top_left, top_middle, top_right
global middle_left, center, middle_right
global bottem_left, bottem_middle, bottem_right
#these are the variables used to check if someone has put their move their already
#0 = empty
#1 = Circle
#2 = X
top_left = 0
top_middle = 0
top_right = 0
middle_left = 0
center = 0
middle_right = 0
bottem_left = 0
bottem_middle = 0
bottem_right = 0
#code for changing turns
turn = 1
def turn_changer():
global turn
if turn == 1:
turn = 2
else:
turn = 1
#board setup
def setup():
size(600,600)
#this hurt my brain trying to fully understand
#lines dividing board
def draw():
for y in range(3):
for x in range(3):
rect(200*x,200*y,200,200)
#hope this is not what geomtry is like
#top left ellipse
if top_left == 1:
ellipse(100,100,150,150)
#top left X
elif top_left == 2:
line(0,0,200,200)
line(200,0,0,200)
#top middle ellipse
if top_middle == 1:
ellipse(300,100,150,150)
#top middle X
elif top_middle == 2:
line(200,0,400,200)
line(400,0,200,200)
#top right ellipse
if top_right == 1:
ellipse(500,100,150,150)
#top right X
elif top_right == 2:
line(400,0,600,200)
line(600,0,400,200)
#middle left ellipse
if middle_left == 1:
ellipse(100,300,150,150)
#middle left X
elif middle_left == 2:
line(0,200,200,400)
line(200,200,0,400)
#middle ellipse
if center == 1:
ellipse(300,300,150,150)
#middle X
elif center == 2:
line(200,200,400,400)
line(400,200,200,400)
#middle right ellipse
if middle_right == 1:
ellipse(500,300,150,150)
#middle right X
elif middle_right == 2:
line(400,200,600,400)
line(600,200,400,400)
#bottem left ellipse
if bottem_left == 1:
ellipse(100,500,150,150)
#bottem left X
elif bottem_left == 2:
line(0,400,200,600)
line(200,400,0,600)
#bottem middle ellipse
if bottem_middle == 1:
ellipse(300,500,150,150)
#bottem middle X
elif bottem_middle == 2:
line(200,400,400,600)
line(400,400,200,600)
#bottem right ellipse
if bottem_right == 1:
ellipse (500,500,150,150)
#bottem right Xw
elif bottem_right == 2:
line(400,400,600,600)
line(600,400,400,600)
#dectects the quardnates where the mouse clicked and prints them
def mousePressed():
println( (mouseX, mouseY) )
#top left square hitbox
if (mouseX > 0 and mouseX < 200) and (mouseY > 0 and mouseY < 200):
top_left =+ turn
turn_changer()
print("top left")
#top middle square hitbox
elif (mouseX > 200 and mouseX < 400) and (mouseY > 0 and mouseY < 200):
top_middle = turn
turn_changer()
print(turn)
print("top middle")
#top right square hitbox
elif (mouseX > 400 and mouseX < 600) and (mouseY > 0 and mouseY < 200):
top_right = turn
turn_changer()
print("top right")
#middle left square hitbox
elif (mouseX > 0 and mouseX < 200) and (mouseY > 200 and mouseY < 400):
middle_left = turn
turn_changer()
print("middle left")
#center square hitbox
elif (mouseX > 200 and mouseX < 400) and (mouseY > 200 and mouseY < 400):
center = turn
turn_changer()
print("middle")
#middle right square hitbox
elif (mouseX > 400 and mouseX < 600) and (mouseY > 200 and mouseY < 400):
middle_right = turn
turn_changer()
print("middle right")
#bottem left square hitbox
elif (mouseX > 0 and mouseX < 200) and (mouseY > 400 and mouseY < 600):
bottem_left = turn
turn_changer()
print("bottem left")
#bottem middle square hitbox
elif (mouseX > 200 and mouseX < 400) and (mouseY > 400 and mouseY < 600):
bottem_middle = turn
turn_changer()
print("bottem middle")
#bottem right square hitbox
elif (mouseX > 400 and mouseX < 600) and (mouseY > 400 and mouseY < 600):
bottem_right = turn
turn_changer()
print("bottem right")
I respect that you're learning on your own, and so I took some time to learn python's basics to give you something to think about. I'm not a python buff (yet), so I may have done some misguided manipulations somewhere (so if a better coder than me is reading this and spots something awful, let me know), but I believe that this is mostly good stuff.
I used class since I tend to think in OOP (and so will you after a while). Instead of seeing a grid with X and O, I see the game like this:
One game is an object.
A Game manages:
A Grid (which is an object, too).
Who's turn it is (and when it's the AI turn, how the AI should play).
When the game ends.
A grid manages:
9 Cases (which are objects, too).
A Case manages:
It draws itself (so... it's coordinates and stuff).
If there's a X or O on it.
If it's been clicked
I fully realize that objects are a huge bump in the learning curve when you start programming, but I'm insisting here because I've seen A LOT of hardcoding in your code, and it's the kind of stuff which will cause you problems when you scale up your projects.
Hardcoding, like how you check which case have been clicked, isn't inherently bad, but it makes everything more difficult. It's part of the things you sometimes learn "the hard way", so here's my advice: when you ninja-code something (short code snippets which are written quickly and won't be part of something bigger), it's not great but it does the job. In any other context, it must be motivated by some specific need to be a good practice, and even there it can be avoided most of the time.
Here's commented code based on what I just wrote. I didn't do the whole tic-tac-toe game, just up to the part where it switch turns between the players or the player/AI (I put a boolean up there that let you switch between human opponent and AI opponent). What is missing is mostly the AI logic (I put a temporary one where it selects the first case it finds) and the victory conditions.
The boolean is currently in "player vs player" mode. Change it to True to let the AI take over the O side.
# Player 1 (X) is human and play first
# Player 2 (O) is cpu
# You can change this boolean to play hotseat with a human if you want:
_AIPlayer = False
# Game own a grid, count turns and do any other game-specific concepts
# One "game of tic-tac-toe" would equal one of this object
class Game:
def __init__(self):
self.Grid = Grid(self) # creating the grid we'll use
self.TurnCount = 0 # first turn is turn number zero
def Render(self):
# when you draw the game, in fact it asks it's grid to draw itself
self.Grid.Render()
def Play(self):
# if it's the CPU's turn, let him play, else the game will wait for the player before going forward
# if there is no cpu player, the mouse can be used by player two
# the difference is that the cpu will do it's turn as a consequence of the player's turn
# and then add +1 to the turn count, while player 2 is exactly like player one but with O instead of X
# the game will check X and O to see who win, not a player class (but it could have been designed that way if needed)
if self.GetCurrentPlayer() == "O" and _AIPlayer:
self.AITurn()
def GetCurrentPlayer(self):
# return which's player is currently playing
if self.TurnCount % 2 == 0:
return "X"
else:
return "O"
def AITurn(self):
# this is a dumb placeholder
# your AI logic will be used here
# for now it just put a O on the first available case
print("AI turn")
for c in self.Grid.Cases:
if c.XO == "":
c.XO = self.GetCurrentPlayer()
break
self.TurnCount += 1
# Grid class is the whole grid
class Grid:
def __init__(self, game):
# the grid knows the game. I could use the global variable instead, but I dislike
# this kind of spaghetti. It would have worked, though.
# It's usually best to make everything you can dynamic, i.e. not hardcoded.
# It's easier to maintain and fix bugs that way, and you can upscale more easily too
# for an example, I could use this code to run several tic-tac-toe games in the
# same window at the same time with only a few modifications
self.Game = game
self.Cases = []
for i in range(3):
for j in range(3):
self.Cases.append(GridCase(i, j))
def Render(self):
# when you draw the grid, in fact it ask it's cases to draw themselves
for c in self.Cases:
c.Render()
def CaseClicked(self, xPos, yPos):
# this checks which case was clicked when it's a player
# since we don't care about the case's coordinated, we ask them if they have been clicked instead
for c in self.Cases:
if c.Clicked(xPos, yPos, self.Game.GetCurrentPlayer()):
self.Game.TurnCount += 1
return
# GridCase is each instance of 1 case in the grid
class GridCase:
def __init__(self, gridX, gridY):
# gridX and gridY are useful to know which case is part of which line
self.gridX = gridX
self.gridY = gridY
# I hardcoded the case's width and height, but you could totally make them dynamic
# and decide "on the fly" how big the grid will be. And it would still work.
self.w = 200 # width
self.h = 200 # height
# these coordinates are in pixels, and are useful to draw the case and for hit detection
self.x = self.w * gridX # x coordinate of the case
self.y = self.h * gridY # y coordinate of the case
# the "content" of the case
self.XO = "" # X or O as a character (it could be anything, I choose to stick to these)
def Render(self):
# the lines positions are dynamic: they'll be calculated from the case's perspective
# every case top left corner is in fact: (self.x, self.y)
rect(self.x, self.y, self.w, self.h)
# if the case has content, it'll be drawn at the same time than the case
if self.XO == "X":
line(self.x , self.y, self.x+self.w, self.y+self.h)
line(self.x, self.y+self.h, self.x+self.w, self.y)
elif self.XO == "O":
ellipse(self.x+(self.w/2),self.y+(self.h/2), self.w*0.75, self.h*0.75)
def SetXO(self, XO):
self.XO = XO
def Clicked(self, xPos, yPos, car):
# if the case is free and the click was inside it's boundaries, then attribute it to the current player
# the return True to tell that a sign was just placed
if self.XO == "" and xPos > self.x and xPos < self.x + self.w and yPos > self.y and yPos < self.y + self.h:
self.XO = car
return True
return False
# globals
_game = Game()
def setup():
size(600,600)
def draw():
# background wipes the screen "clean" (here it paints it black)
# then we can draw the current state of the grid
# here we could do without but I wanted you to know about it
background(0)
# draw the grid, then let the players do their thing
_game.Render()
# here you should check for game end conditions (victory or draw)
_game.Play()
def mouseClicked():
# listeing to mouse clicks
_game.Grid.CaseClicked(mouseX, mouseY)
You should copy and paste this code in a Processing.py IDE and try it. Fiddle around and read the comments. You can learn a lot here if you try. If you have questions, ask away in the comments with my handle and I'll come back and give you a hand.
And... have fun!
When the button is pressed check if the turn is equal to 1 or 2 and with that u tell the program to display an cross or a circle instead of making a function to change that value
Hope this helps!
There are SO MANY WAYS you could do this...
You can flip a variable (kinda like you just showed). Since there are only two players, I would probably flip a boolean instead: myBoolean = !myBoolean after every turn.
You can count the turns and use the modulo operator. Then you both know which turn it is right now AND the total number of turns for the current game. Let's say that you have a global TurnCount variable. If you do TurnCount % 2 the result will either be 0 or 1, making it a surefire way to know which turn it is. This operator is really useful and you should remember it either way!
If there are no difference in the gameplay between player 1 and 2 except for their X and O, you can flip between the character 'X' and the character 'O' instead of 1 and 2 like in your code snippet. This variable can be used to show visually which symbol will placed or straight up to place one symbol or the other. Simple and efficient.
So it mostly depends on how ninja you code will be. If you're doing a "simpel hot seat" where players takes turn clicking with the same mouse, method 3 is great. If you want to show "statistics" after the game, method 2 will work nicely. Method 1 will work too, but it's more rough, even if it's simple. You can add more code if you need tailored advice.
Have fun!
Set the variable 'turn' as a global (outside of the 'turn_changer' function / making sure this code is only ran once, not every time your game loops).
Run your game logic, with the player (X or O) being determined by the value of 'turn'.
After the player makes their move call 'turn_changer' so the turn changes.
Repeat.
Using the code you provided, I added this:
def game():
print (turn)
turn_changer()
print (turn)
turn_changer()
print (turn)
if __name__ == "__main__":
game()
and the turn_changer() function seems to work correctly
I wrote this physics simulation in pygame and the collision mechanism is not working properly. It seems to work when I collide the player character with the wall from above the wall or from the left and not work for collisions from the bottom or from the right
I have been trying to find this bug for some time but I just have no clue as to what might cause this. I am using python 3.7.3 and pygame 1.9.5 (latest versions as of date)
I am sorry for pasting an entire file but I just have no Idea where the problem is
import pygame # import the pygame library to have access to game building tools
import math
# these variables will be used to hold game objects and draw them
rigid_bodies = []
g = 100
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PURPLE = (127, 0, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)
class RigidBody(pygame.Rect):
"""
represents a rectangular object that acts according to newton's laws of motion
"""
def __init__(self, canvas, color, m, u, x, y, w, h):
"""
called automatically when a new object is created to initialize the object
:param canvas: the canvas on which to draw the object
:param color: the color of the object
:param m: the mass of the object
:param u: Coefficient of friction
:param x: the starting position of the object on the x axis
:param y: the starting position of the object on the y axis
:param w: the width of the object
:param h: the height of the object
"""
super().__init__(x, y, w, h) # initialize the parent Rect object
self.canvas = canvas
self.color = color
self.m = m
self.u = u
self.x_speed = 0 # the speed of the object on the x axis
self.y_speed = 0 # the speed of the object on the y axis
def apply_force(self, axis, F, initiator=None):
"""
used to apply force on the object
:param axis: the axis of the force
:param F: the amount of force to apply
:param initiator: the object that is applying the force
"""
a = F / self.m # calculate the acceleration the object should have
if axis == 'y':
self.y_speed += a
elif axis == 'x':
self.x_speed += a
if initiator:
initiator.apply_force(axis, -1 * F) # apply normal force
print('colliding')
def inertia(self):
"""
shall be run every frame to make the object move according to its speed
if possible and take the necessary steps if not
"""
# go:
self.x += self.x_speed
self.y += self.y_speed
for body in rigid_bodies:
if self.colliderect(body): # if collide with another object:
self.x -= self.x_speed # go back
self.y -= self.y_speed
body.apply_force('x', self.m * self.x_speed, self) # and apply force on that object
body.apply_force('y', self.m * self.y_speed, self)
break
def draw(self):
"""
shall be run every frame to draw the object on the canvas
"""
pygame.draw.rect(self.canvas, self.color, (self.x, self.y, self.w, self.h))
class Controller:
def __init__(self, character, F):
"""
initialize the controller object
:param character: the character to control
:param F: the force to apply to the character for every frame a button is being pressed
"""
self.character = character
self.up = 0 # whether to move up or not
self.down = 0 # whether to move down or not
self.left = 0 # whether to move left or not
self.right = 0 # whether to move right or not
self.F = F
def stop(self):
"""
stops applying force on the object
"""
self.up = 0
self.down = 0
self.left = 0
self.right = 0
def run(self):
"""
shall be run every frame to apply force on the character according to user input
"""
self.character.apply_force('y', -self.F * self.up)
self.character.apply_force('y', self.F * self.down)
self.character.apply_force('x', -self.F * self.left)
self.character.apply_force('x', self.F * self.right)
def main():
"""
the main function contains the main loop
that runs repeatedly while the game is running
"""
crashed = False # tells if the program crashed or if the window was closed
pygame.init() # required to use pygame
canvas = pygame.display.set_mode((1000, 700)) # define the canvas
clock = pygame.time.Clock() # will be used to limit the number of times a loop runs per second
pygame.display.set_caption('the dot game V2')
character = RigidBody(canvas, WHITE, 1000, 0.3, 500, 500, 20, 50) # initialize the character
player = Controller(character, 500) # initialize the controller
rigid_bodies.append(RigidBody(canvas, WHITE, math.inf, 0, 300, 300, 300, 20)) # initialize the wall
while not crashed:
# handle inputs:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.MOUSEBUTTONUP:
pass
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
player.up = 1
elif event.key == pygame.K_DOWN:
player.down = 1
elif event.key == pygame.K_LEFT:
player.left = 1
elif event.key == pygame.K_RIGHT:
player.right = 1
elif event.type == pygame.KEYUP:
player.stop()
player.run()
character.inertia()
canvas.fill(BLACK)
character.draw()
for body in rigid_bodies:
body.draw()
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
I suspect that the problem is with either the "inertia" or the "apply_force" functions but I just cant figure out WHAT is the problem with those functions
The character should stop moving every time it hits the wall, but when it hits the wall from below or from the right it gets stuck and can only move up or to the left
The issue is caused by casting a floating point value to int and can be solved by:
stored_pos = (self.x, self.y)
self.x += self.x_speed
self.y += self.y_speed
for body in rigid_bodies:
if self.colliderect(body): # if collide with another object:
self.x, self.y = stored_pos
Note, that
self.x -= self.x_speed
self.y -= self.y_speed
is not the inverse operation of
self.x += self.x_speed
self.y += self.y_speed
e.g: a = 2 and b = 0.5
int(a + b) == int(2 + 0.5) == 2
int(a - b) == int(2 - 0.5) == 1
The solution is to store the original values of self.x and self.y
stored_pos = (self.x, self.y)
and to restore it in the case of a collision:
self.x, self.y = stored_pos