Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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