I'm new to python so please forgive me if I'm misnaming pygame objects. I've been tasked to build a virtual Pachinko gaming machine. I'm having trouble getting the coordinates of the ball as it falls through the window. I need the coordinates to keep track of score and reset the loops so the user can drop another ball once it bottoms out.
Here's my source code.
#Project specific libraries
import pygame #https://www.pygame.org/news
import pymunk #http://www.pymunk.org/en/latest/
import pymunk.util
import pymunk.pygame_util
import tkinter #https://docs.python.org/2/library/tkinter.html
#Standard libraries
import sys
import math
import random
import os
import time
#Import ALL tools from tkinter & pygame libraies
from tkinter import *
from pygame import *
#Constants for object to object interaction
COLLTYPE_FLOOR = 3
COLLTYPE_BOUNCER = 2
COLLTYPE_BALL = 1
#****************************************************************************
def goal_reached(arbiter, space1, data):
ball_i, floor_i = arbiter.shapes
space_i = space1
space_i.remove(ball_i, ball_i.body)
remove_from_ball_list(ball_i)
return True
#*************************************************************
main = Tk()
main.resizable(width=False, height=False)
main.title("Pachinko")
embed = Frame(main, width = 500, height = 500)
embed.pack() #packs window to the left
os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
screen = pygame.display.set_mode((500,500))
screen.fill(pygame.Color(255,215,255))
clock = pygame.time.Clock()
#List of ball "objects"
balls = []
#might not need balls_to_remove List
balls_to_remove = []
#velocity, gravity
space = pymunk.Space()
space.gravity = 0, -200
#Floor boundaries
floor = pymunk.Segment(space.static_body, (0.0, 10.0), (500.0, 10.0), 1.0)
floor.collision_type = COLLTYPE_FLOOR
space.add(floor)
#Left wall boundaries
left_wall = pymunk.Segment(space.static_body, (0.0, 500.0), (0.0, 0.0), 1.0)
left_wall.friction = 1.0
left_wall.elasticity = 0.9
left_wall.collision_type = COLLTYPE_BOUNCER
space.add(left_wall)
#Right wall boundaries
right_wall = pymunk.Segment(space.static_body, (500.0, 500.0), (500.0, 0.0), 1.0)
right_wall.friction = 1.0
right_wall.elasticity = 0.9
right_wall.collision_type = COLLTYPE_BOUNCER
space.add(right_wall)
draw_options = pymunk.pygame_util.DrawOptions(screen)
space.debug_draw(draw_options)
#Generate a fixed field of pins
done = 0
x_shift = 45
y_shift = 150
step = 0
tier = 0
while(done == 0):
variance = random.randint(1, 15)
pin_radius = random.randint(14, 17)
newPin = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
x = x_shift + variance
y = y_shift + variance
newPin.position = x, y
shape = pymunk.Circle(newPin, pin_radius)
shape.collision_type = COLLTYPE_BOUNCER
space.add(newPin, shape)
x_shift += 85
step += 1
if(step == 5): #Tier one
x_shift = 100
y_shift += 60
if(step == 10): #Tier two
x_shift = 50
y_shift += 60
if(step == 15): #Tier three
x_shift = 100
y_shift += 60
if(step == 20): #Tier four
x_shift =50
y_shift += 60
if(step == 25): #Tier five
x_shift = 100
y_shift += 60
done = 1
#Generate the five poles (left to right)
step = 0
x_shift = 100
while(step < 4):
pole0 = pymunk.Segment(space.static_body, (x_shift, 100.0), (x_shift, 10.0), 5.0)
pole0.friction = 1.0
pole0.elasticity = 0.9
pole0.collision_type = COLLTYPE_BOUNCER
space.add(pole0)
step += 1
x_shift += 100
pygame.display.flip()
pygame.display.init()
pygame.display.update()
#https://stackoverflow.com/questions/23410161/pygame-collision-code
h = space.add_collision_handler(COLLTYPE_BALL, COLLTYPE_FLOOR)
h.begin = goal_reached
def remove_from_ball_list(temp1):
#print("where in list is it?")
for ball in balls:
if temp1 == ball:
#print("Time to remove from the list")
balls.remove(ball)
#Primary game loop
ticks = 50
play = True
while play == True:
mouseClick = pygame.event.get()
dropHeight = 440
for event in mouseClick:
if event.type == pygame.MOUSEBUTTONUP:
mouseX, mouseY = pygame.mouse.get_pos()
ticks = 0
#keep making new balls & pins
if ticks == 0:
step = 0
x_shift = 0
y_shift = 0
#Generate the new ball
mass = 1
inertia = pymunk.moment_for_circle(mass, 0, 14, (0, 0))
radius = 12
ball = pymunk.Body(mass, inertia)
#Keep the ball in bounds when user drops
if(mouseX < 25):
mouseX = 10
if(mouseX > 480):
mouseX = 490
ball.position = mouseX, dropHeight
shape = pymunk.Circle(ball, radius)
shape.collision_type = COLLTYPE_BALL
space.add(ball, shape)
balls.append(shape)
ticks = 50
pygame.draw.line(screen, (255,0,255), (20,60), (480,60), 2)
space.step(1/50.0)
space.debug_draw(draw_options)
pygame.display.update()
pygame.display.flip()
screen.fill(pygame.Color(255,215,255))
clock.tick(50)
#ticks -= 1
main.update()
And here is the specific piece of code I'd like to add the feature:
#Primary game loop
ticks = 50
play = True
while play == True:
mouseClick = pygame.event.get()
dropHeight = 440
for event in mouseClick:
if event.type == pygame.MOUSEBUTTONUP:
mouseX, mouseY = pygame.mouse.get_pos()
ticks = 0
#keep making new balls & pins
if ticks == 0:
step = 0
x_shift = 0
y_shift = 0
#Generate the new ball
mass = 1
inertia = pymunk.moment_for_circle(mass, 0, 14, (0, 0))
radius = 12
ball = pymunk.Body(mass, inertia)
#Keep the ball in bounds when user drops
if(mouseX < 25):
mouseX = 10
if(mouseX > 480):
mouseX = 490
ball.position = mouseX, dropHeight
shape = pymunk.Circle(ball, radius)
shape.collision_type = COLLTYPE_BALL
space.add(ball, shape)
balls.append(shape)
ticks = 50
pygame.draw.line(screen, (255,0,255), (20,60), (480,60), 2)
space.step(1/50.0)
space.debug_draw(draw_options)
pygame.display.update()
pygame.display.flip()
screen.fill(pygame.Color(255,215,255))
clock.tick(50)
#ticks -= 1
main.update()
I would like to print the ball coordinates to the terminal so I can add scoring and restart features. I feel like that I'm missing a very simple solution.
It seems like the balls are collected in a list, balls
. So you can just loop through it to get all the info you need. For example, if you put the below code in the while loop it will print the location of each ball each frame.
for b in balls:
print("ball position", b.body.position)
However, maybe you do not need to check this yourself each frame? You already have a goal_reached function, that is called once the ball reached the goal if I understand it correctly. In there you can update the score and toggle something to allow the player to add another ball.