Today, we’re going to dive into something really fun and creative: we’re going to build a game using Nuke and PySide2! Yes, you heard that right—a game! We’ll create a game called ‘Catch the Falling Nuke Nodes.’ Using ChatGPT
Before we get started, let’s talk about the concept. In ‘Catch the Falling Nuke Nodes,’ you’ll control a paddle at the bottom of the screen to catch falling Nuke nodes. Each node will have a different score associated with it—some will give you points, while others will deduct points! The goal is to score 50 points before time runs out.
First things first, make sure you have Nuke installed with PySide2. If you’re not familiar with PySide2, it’s a set of Python bindings for the Qt libraries, allowing us to create a user interface in our Nuke scripts. I’ll leave links in the description for installation instructions.”
This script is tested in Nuke 15, The following content is intended for educational purposes only. While I’ve done my best to provide accurate and helpful information, please remember that running scripts in Nuke or any other software can potentially lead to unexpected behavior, including crashes or data loss. Always make sure to save your work and run scripts at your own risk. Let’s get started!”
import random
from PySide2.QtCore import Qt, QTimer, QRectF
from PySide2.QtWidgets import QWidget, QLabel, QMessageBox, QPushButton
from PySide2.QtGui import QPainter, QColor, QBrush, QFont, QLinearGradient, QPalette
import nuke
# Global variable to hold the game instance
game_instance = None
class FallingObjectGame(QWidget):
def __init__(self):
super(FallingObjectGame, self).__init__()
self.setWindowTitle('Catch the Falling Nuke Nodes')
self.setGeometry(100, 100, 400, 600)
# Set background with gradient
palette = QPalette()
gradient = QLinearGradient(0, 0, 0, 600)
gradient.setColorAt(0, QColor(120, 120, 120))
gradient.setColorAt(1, QColor(120, 120, 120))
palette.setBrush(self.backgroundRole(), QBrush(gradient))
self.setPalette(palette)
# Paddle settings
self.paddle_width = 100
self.paddle_height = 20
self.paddle_x = (self.width() - self.paddle_width) // 2
self.paddle_y = self.height() - self.paddle_height - 10
self.paddle_speed = 20
# Falling object settings
self.object_height = 20
self.falling_objects = []
self.object_speed = 5
# Game score and timer
self.score = 0
self.time_limit = 30 # 30 seconds
self.timer_label = QLabel(f'Time Left: {self.time_limit}', self)
self.timer_label.setStyleSheet("color: black; font-weight: bold;")
self.timer_label.move(10, 30)
self.score_label = QLabel(f'Score: {self.score}', self)
self.score_label.setStyleSheet("color: black; font-weight: bold;")
self.score_label.move(10, 10)
# Set up the game timer
self.game_timer = QTimer(self)
self.game_timer.timeout.connect(self.update_game)
self.game_timer.start(50)
# Add new objects timer
self.object_timer = QTimer(self)
self.object_timer.timeout.connect(self.add_falling_object)
self.object_timer.start(1000) # Add a new object every second
# Countdown timer
self.countdown_timer = QTimer(self)
self.countdown_timer.timeout.connect(self.update_time)
self.countdown_timer.start(1000) # Update every second
self.win_score = 50 # Score needed to win
self.game_over = False
# Nuke node names with corresponding points and colors
self.node_names = {
"Approved": (5, QColor(10, 155, 50)), # Green
"Feedback": (-5, QColor(155, 10, 50)), # Red
"Blur": (3, QColor(100, 100, 155)), # Light Blue
"Merge": (0, QColor(155, 155, 40)), # Yellow
"Transform": (0, QColor(155, 165, 20)), # Orange
"Grade": (3, QColor(75, 70, 130)), # Indigo
"Keyer": (4, QColor(148, 30, 211)), # Violet
"Roto": (2, QColor(0, 55, 155)), # Cyan
"Reformat": (1, QColor(255, 20, 147)), # Deep Pink
"Grade": (2, QColor(128, 128, 128)) # Gray
}
# Target points label at the top corner
self.target_points_label = QLabel('Target Points: 50', self)
self.target_points_label.setStyleSheet("color: black; font-weight: bold;")
self.target_points_label.move(300, 10) # Positioned at the top right corner
# Restart button
self.restart_button = QPushButton('Restart', self)
self.restart_button.setStyleSheet("color: white; background-color: green; border-radius: 10px; font-weight: bold;")
self.restart_button.move(150, 550)
self.restart_button.clicked.connect(self.restart_game)
self.restart_button.setVisible(False) # Initially hidden
def add_falling_object(self):
"""Adds a new falling object at a random x position with a random speed and name."""
x = random.randint(0, self.width() - 100) # Width is random between 60 and 100
width = random.randint(60, 100) # Random width for the rectangle
speed = random.randint(2, 8) # Random speed between 2 and 8
name = random.choice(list(self.node_names.keys())) # Randomly select a node name
color = self.node_names[name][1] # Get the corresponding color for the node
self.falling_objects.append((QRectF(x, 0, width, self.object_height), color, speed, name))
def update_game(self):
"""Updates the game state, moving objects and detecting collisions."""
if not self.game_over:
self.move_objects()
self.check_collisions()
self.repaint()
else:
self.game_timer.stop()
self.object_timer.stop()
self.countdown_timer.stop()
self.show_game_over()
def update_time(self):
"""Decreases the time left and checks for game over."""
self.time_limit -= 1
self.timer_label.setText(f'Time Left: {self.time_limit}')
if self.time_limit <= 0:
self.game_over = True
def move_objects(self):
"""Move the falling objects down the screen."""
for i, (obj, color, speed, name) in enumerate(self.falling_objects):
obj.moveTop(obj.top() + speed)
# Remove objects that have fallen off the screen
self.falling_objects = [(obj, color, speed, name) for (obj, color, speed, name) in self.falling_objects if obj.top() <= self.height()]
def check_collisions(self):
"""Check for collisions between the paddle and falling objects."""
for obj, color, speed, name in self.falling_objects:
if obj.intersects(QRectF(self.paddle_x, self.paddle_y, self.paddle_width, self.paddle_height)):
self.falling_objects.remove((obj, color, speed, name))
self.score += self.node_names[name][0] # Update score based on the node name
self.score_label.setText(f'Score: {self.score}')
# Check for win condition
if self.score >= self.win_score:
self.game_over = True
break
def paintEvent(self, event):
"""Draw the paddle and the falling objects."""
painter = QPainter(self)
# Draw paddle with rounded corners
paddle_rect = QRectF(self.paddle_x, self.paddle_y, self.paddle_width, self.paddle_height)
painter.setBrush(QBrush(QColor(0, 150, 0)))
painter.drawRoundedRect(paddle_rect, 10, 10)
# Draw falling objects with names
for obj, color, speed, name in self.falling_objects:
painter.setBrush(QBrush(color))
painter.drawRoundedRect(obj, 5, 5) # Rounded corners for falling objects
# Draw the node name inside the object
painter.setPen(QColor(255, 255, 255)) # White text
painter.setFont(QFont('Arial', 10))
painter.drawText(obj, Qt.AlignCenter, name)
def keyPressEvent(self, event):
"""Handle left/right arrow key events to move the paddle."""
if event.key() == Qt.Key_Left and self.paddle_x > 0:
self.paddle_x -= self.paddle_speed
elif event.key() == Qt.Key_Right and self.paddle_x < (self.width() - self.paddle_width):
self.paddle_x += self.paddle_speed
self.repaint()
def show_game_over(self):
"""Show game over message and restart button."""
QMessageBox.information(self, "Game Over", f"Game Over! Your Score: {self.score}")
self.restart_button.setVisible(True) # Show the restart button
def restart_game(self):
"""Restart the game by resetting variables and restarting timers."""
self.score = 0
self.time_limit = 30
self.falling_objects.clear()
self.game_over = False
self.restart_button.setVisible(False) # Hide the restart button
# Reset labels
self.score_label.setText(f'Score: {self.score}')
self.timer_label.setText(f'Time Left: {self.time_limit}')
# Restart timers
self.game_timer.start(50)
self.object_timer.start(1000)
self.countdown_timer.start(1000)
self.repaint()
# Function to start the game
def start_game():
global game_instance
if game_instance is None:
game_instance = FallingObjectGame()
game_instance.show()
# Execute the game
start_game()