Skip to content

Instantly share code, notes, and snippets.

@dbr
Created April 5, 2010 12:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dbr/356294 to your computer and use it in GitHub Desktop.
Save dbr/356294 to your computer and use it in GitHub Desktop.
Pong. In Nuke.
"""Pong.
In Nuke.
"""
import nuke
import time
from random import random
import threading
class Player1Score(Exception):
pass
class Player2Score(Exception):
pass
class Ball(object):
def __init__(self, node):
self.node = node
self.vx = 4
self.vy = 0
# Number of nudge()'s since last collision.
# Used to prevent multiple collisions on the same object in
# quick sucession (which makes the ball get stuck in the object)
self.steps_since_collision = 0
self.delay_between_collisions = 5
# Getter/setter for ball location
def _setxy(self, v):
x, y = v
nuke.executeInMainThread(self.node.setXYpos, (x, y))
time.sleep(0.001)
def _getxy(self):
x = self.node.xpos()
y = self.node.ypos()
return x, y
xy = property(_getxy, _setxy)
def nudge(self):
"""Moves ball with x/y velocity"""
x, y = self.xy
self.xy = (x + self.vx, y + self.vy)
self.steps_since_collision += 1
def reset(self, gamebox):
"""Reset ball to centre. Reset velocity"""
x, y = gamebox.xpos(), gamebox.ypos()
w, h = gamebox.screenWidth(), gamebox.screenHeight()
cx = x + (w/2)
cy = y + (h/2)
r = 2 - (random() * 4)
if self.vx > 0:
self.vx, self.vy = 4, 0
else:
self.vx, self.vy = -4, 0
nuke.executeInMainThread(self.node.setXYpos, (cx, cy))
def check_paddle(self, paddle):
"""Checks collision with paddles"""
if self.steps_since_collision < self.delay_between_collisions:
return
x, y = self.xy
cx, cy = paddle.xpos(), paddle.ypos()
cw, ch = paddle.screenWidth(), paddle.screenHeight()
if y > cy and y < (cy + ch):
# In correct y location
if (x > (cx)) and (x < (cx + cw)):
self.vx = -self.vx
# Add randomness to bounce
self.vy = self.vy + (1.0 - (random() * 2.0))
self.nudge()
self.steps_since_collision = 0
def check_gamebox(self, gamebox):
"""Checks for collisions with the edge of game box, and raises the
appropriate Player{n}Score exception"""
if self.steps_since_collision < self.delay_between_collisions:
return
sx, sy = gamebox.xpos(), gamebox.ypos()
w, h = gamebox.screenWidth(), gamebox.screenHeight()
maxx = sx + w
maxy = sy + h
x, y = self.xy
if x < sx:
self.vx = -self.vx
self.nudge()
self.steps_since_collision = 0
raise Player1Score()
elif x > maxx:
self.vx = -self.vx
self.nudge()
self.steps_since_collision = 0
raise Player2Score()
elif y < sy:
self.vy = -self.vy
self.nudge()
x, y = self.xy
self.xy = (x, sy)
self.steps_since_collision = 0
elif y > maxy:
self.vy = -self.vy
self.nudge()
x, y = self.xy
self.xy = (x, maxy)
self.steps_since_collision = 0
class Game(threading.Thread):
def __init__(self, gamebox, ball, player1, player2):
threading.Thread.__init__(self)
self.gamebox = gamebox
self.ball = ball
self.left = player1
self.right = player2
self.ball = Ball(self.ball)
self.stop = False
def deletenodes(self):
for x in [self.gamebox, self.left, self.right]:
nuke.delete(nuke.toNode(x.name()))
nuke.delete(self.ball.node)
def gameloop(self):
self.ball.reset(self.gamebox)
time.sleep(0.1)
while not self.stop:
self.ball.nudge()
toincrement = None
try:
self.ball.check_gamebox(self.gamebox)
except Player1Score:
print "Player 1 scored"
toincrement = self.gamebox['p1_score']
except Player2Score:
print "Player 2 scored"
toincrement = self.gamebox['p2_score']
if toincrement is not None:
cur = nuke.executeInMainThreadWithResult(toincrement.value)
if cur is None:
cur = 0
new = cur + 1
nuke.executeInMainThreadWithResult(toincrement.setValue, new)
self.ball.reset(self.gamebox)
self.ball.check_paddle(paddle = self.left)
self.ball.check_paddle(paddle = self.right)
time.sleep(0.01)
def run(self):
try:
self.gameloop()
except Exception, e:
# Exception in thread doesn't give a useful traceback
# to Nuke console, print one.
import traceback
traceback.print_exc()
raise
def _nudgeplayer(node, vertical):
y = node.ypos()
node.setYpos(y + vertical)
def nudge_up(left = False, right = False, large = False):
global pong
if left:
node = pong.left
elif right:
node = pong.right
else:
raise ValueError("left or right must be True")
_nudgeplayer(node, -40 if large else -20)
def nudge_down(left = False, right = False, large = False):
global pong
if left:
node = pong.left
elif right:
node = pong.right
else:
raise ValueError("left or right must be True")
_nudgeplayer(node, 40 if large else 20)
global pong
pong = None
def stop_pong():
global pong
if pong is None:
return
else:
print "Stopping pong.."
pong.stop = True
pong.join()
pong.deletenodes()
pong = None
def start_pong():
stop_pong()
# Make game box
gamebox = nuke.toNode("PONG")
if gamebox is None:
gamebox = nuke.nodes.BackdropNode(bdwidth = 1000, bdheight = 500)
p1s = nuke.Int_Knob('p1_score', 'player 1 score')
p2s = nuke.Int_Knob('p2_score', 'player 2 score')
gamebox.addKnob(p1s)
gamebox.addKnob(p2s)
gamebox['tile_color'].setValue(1)
ball = nuke.toNode("ball")
if ball is None:
ball = nuke.nodes.Dot()
# Make paddles
player1, player2 = nuke.toNode("player1"), nuke.toNode("player2")
if player1 is None:
player1 = nuke.nodes.BackdropNode(bdwidth = 40, bdheight = 100, name = "player1")
player1.setXpos(gamebox.xpos())
if player2 is None:
player2 = nuke.nodes.BackdropNode(bdwidth = 40, bdheight = 100, name = "player2")
player2.setXpos(
(gamebox.xpos() + (gamebox.screenWidth() - 40)))
global pong
pong = Game(
gamebox = gamebox,
ball = ball,
player1 = player1,
player2 = player2)
pong.start()
def main():
mn = nuke.menu("Nodes")
mp = mn.addMenu("Pong")
mp.addCommand(
"start pong",
lambda: start_pong(),
"alt+p")
mp.addCommand("stop pong",
lambda: stop_pong(),
"alt+q")
mp.addSeparator()
mp.addCommand("p1 - up",
lambda: nudge_up(left=True),
"Up")
mp.addCommand("p1 - up large",
lambda: nudge_up(left=True, large=True),
"Shift+Up")
mp.addCommand("p1 - down",
lambda: nudge_down(left=True),
"Down")
mp.addCommand("p1 - down large",
lambda: nudge_down(left=True, large=True),
"Shift+Down")
mp.addSeparator()
mp.addCommand("p2 - up",
lambda: nudge_up(right=True),
"w")
mp.addCommand("p2 - up large",
lambda: nudge_up(right=True, large=True),
"Shift+w")
mp.addCommand("p2 - down",
lambda: nudge_down(right=True),
"s")
mp.addCommand("p2 - down large",
lambda: nudge_down(right=True, large=True),
"Shift+s")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment