Skip to content

Instantly share code, notes, and snippets.

@AaronO
Created December 4, 2022 00:21
Show Gist options
  • Save AaronO/11ca97312bb830649e15e0a062958fd4 to your computer and use it in GitHub Desktop.
Save AaronO/11ca97312bb830649e15e0a062958fd4 to your computer and use it in GitHub Desktop.
GPT-Pong's code, created by ChatGPT, fixed by AaronO
import SpriteKit
import AVFoundation
class GameScene: SKScene {
// Create a ball node
let ball = SKShapeNode(circleOfRadius: 10)
// Create player paddles
let player1 = SKShapeNode(rectOf: CGSize(width: 10, height: 50))
let player2 = SKShapeNode(rectOf: CGSize(width: 10, height: 50))
// Create score labels
let player1ScoreLabel = SKLabelNode(text: "0")
let player2ScoreLabel = SKLabelNode(text: "0")
// Create a game state to track the score and ball velocity
var gameState = GameState()
// Track the touch positions for each player's paddle
var player1Touch: UITouch?
var player2Touch: UITouch?
// Create an emitter node for the confetti animation
let confettiEmitter = SKEmitterNode()
let EASY_DIFFICULTY: CGFloat = 99
let MEDIUM_DIFFICULTY: CGFloat = 50
let HARD_DIFFICULTY: CGFloat = 10
override func didMove(to view: SKView) {
// Set the background color to black
self.backgroundColor = SKColor.black
// Set the ball properties
ball.position = CGPoint(x: frame.midX, y: frame.midY)
ball.fillColor = SKColor.white
ball.strokeColor = SKColor.white
addChild(ball)
// Set the player paddles' positions and colors
player1.position = CGPoint(x: frame.minX + 25, y: frame.midY)
player1.fillColor = SKColor.white
player1.strokeColor = SKColor.white
addChild(player1)
player2.position = CGPoint(x: frame.maxX - 25, y: frame.midY)
player2.fillColor = SKColor.white
player2.strokeColor = SKColor.white
addChild(player2)
// Set the score labels' positions and colors
player1ScoreLabel.position = CGPoint(x: frame.midX - 50, y: frame.maxY - 40)
player1ScoreLabel.fontColor = SKColor.white
addChild(player1ScoreLabel)
player2ScoreLabel.position = CGPoint(x: frame.midX + 50, y: frame.maxY - 40)
player2ScoreLabel.fontColor = SKColor.white
addChild(player2ScoreLabel)
// Set the ball's initial velocity
gameState.ballVelocity = CGVector(dx: 200, dy: 200)
// Create a circle shape node for the confetti texture
let confettiShape = SKShapeNode(circleOfRadius: 5)
confettiShape.fillColor = SKColor.white
confettiShape.strokeColor = SKColor.white
// Create an SKTexture object from the circle shape node
let confettiTexture = self.view!.texture(from: confettiShape)
// Configure the confetti emitter node
// confettiEmitter.particleTexture = SKTexture(imageNamed: "confetti")
confettiEmitter.particleTexture = confettiTexture
confettiEmitter.particleBirthRate = 300
confettiEmitter.particleLifetime = 5
confettiEmitter.particleColor = SKColor.green
confettiEmitter.particleColorBlendFactor = 1
confettiEmitter.particleBlendMode = SKBlendMode.add
confettiEmitter.position = CGPoint(x: frame.midX, y: frame.minY)
confettiEmitter.particlePositionRange = CGVector(dx: frame.size.width/8, dy: frame.size.height/8)
confettiEmitter.particleSpeed = 100
confettiEmitter.particleSpeedRange = 50
confettiEmitter.emissionAngle = 3.14
confettiEmitter.emissionAngleRange = 3.14
confettiEmitter.particleAlpha = 1
confettiEmitter.particleAlphaRange = 0.5
confettiEmitter.particleAlphaSpeed = -1
confettiEmitter.particleScale = 0.5
confettiEmitter.particleScaleRange = 0.25
confettiEmitter.particleScaleSpeed = -0.5
confettiEmitter.particleRotation = 3.14
confettiEmitter.particleRotationRange = 3.14
confettiEmitter.particleRotationSpeed = -3
confettiEmitter.particleLifetimeRange = 3
}
override func update(_ interval: TimeInterval) {
// fixedby(Aaron): compute delta
let t = CGFloat(interval)
let delta = t - gameState.prevT
gameState.prevT = t
// Move the ball based on its velocity
ball.position.x += gameState.ballVelocity.dx * delta
ball.position.y += gameState.ballVelocity.dy * delta
// Check if the ball has collided with a paddle
if ball.frame.intersects(player1.frame) {
gameState.ballVelocity.dx = abs(gameState.ballVelocity.dx)
} else if ball.frame.intersects(player2.frame) {
gameState.ballVelocity.dx = -abs(gameState.ballVelocity.dx)
}
// Check if the ball has gone off the top or bottom of the screen
if ball.position.y > frame.maxY || ball.position.y < frame.minY {
gameState.ballVelocity.dy = -gameState.ballVelocity.dy
}
// Check if the ball has gone off the left or right side of the screen
if ball.position.x < frame.minX {
player2Scored()
didScore()
} else if ball.position.x > frame.maxX {
player1Scored()
didScore()
}
// Move the player paddles based on the touch positions
if let touch = player1Touch {
player1.position.y = touch.location(in: self).y
}
if let touch = player2Touch {
player2.position.y = touch.location(in: self).y
}
// AI control inactive players
if player1Touch == nil {
// Calculate the AI's next move based on the ball's position and velocity
let nextMove = calculateAIMove(player: player1, ball: ball, ballVelocity: gameState.ballVelocity, difficulty: HARD_DIFFICULTY)
// Update player 1's paddle position based on the AI's next move
player1.position.y += nextMove
}
if player2Touch == nil {
// Calculate the AI's next move based on the ball's position and velocity
let nextMove = calculateAIMove(player: player2, ball: ball, ballVelocity: gameState.ballVelocity, difficulty: EASY_DIFFICULTY)
// Update player 2's paddle position based on the AI's next move
player2.position.y += nextMove
}
}
// Calculate the AI's next move based on the ball's position and velocity
func calculateAIMove(player: SKShapeNode, ball: SKShapeNode, ballVelocity: CGVector, difficulty: CGFloat) -> CGFloat {
// Calculate the ball's projected position after a small time interval
let ballProjectedPosition = CGPoint(
x: ball.position.x + (ballVelocity.dx * 0.05),
y: ball.position.y + (ballVelocity.dy * 0.05)
)
// Calculate the AI's next move based on the ball's projected position
let nextMove = ballProjectedPosition.y - player.position.y
// Slow down the AI's movement based on the difficulty level
let movementSpeed = max(1 - difficulty / 100, 0)
let adjustedMove = nextMove * movementSpeed
// Limit the AI's next move to the screen's bounds
let minY = self.frame.minY + player.frame.height / 2;
let maxY = self.frame.maxY - player.frame.height / 2;
return max(min(adjustedMove, maxY), minY)
}
func player1Scored() {
// Increment player 1's score
gameState.player1Score += 1
// Update the score label
player1ScoreLabel.text = "\(gameState.player1Score)"
// Reset the ball's position and velocity
ball.position = CGPoint(x: frame.midX, y: frame.midY)
gameState.ballVelocity = CGVector(dx: 200, dy: 200)
}
func player2Scored() {
// Increment player 2's score
gameState.player2Score += 1
// Update the score label
player2ScoreLabel.text = "\(gameState.player2Score)"
// Reset the ball's position and velocity
ball.position = CGPoint(x: frame.midX, y: frame.midY)
gameState.ballVelocity = CGVector(dx: -200, dy: -200)
}
// Start the confetti animation when a player scores
func didScore() {
// Add the confetti emitter node to the scene
addChild(confettiEmitter)
confettiEmitter.resetSimulation()
confettiEmitter.run(SKAction.sequence([
SKAction.wait(forDuration: 1),
SKAction.removeFromParent()
]))
// Victory sound
playVictorySound()
}
func playVictorySound() {
AudioServicesPlaySystemSound(1057)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Get the touch position
guard let touch = touches.first else {
return
}
let touchPosition = touch.location(in: self)
// Check which player's paddle the touch corresponds to
if touchPosition.x < frame.midX {
player1Touch = touch
} else {
player2Touch = touch
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// Get the touch position
guard let touch = touches.first else {
return
}
let touchPosition = touch.location(in: self)
// Check which player's paddle the touch corresponds to
if touchPosition.x < frame.midX {
player1Touch = touch
} else {
player2Touch = touch
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
// Check which player's paddle the touch corresponds to
for touch in touches {
if touch == player1Touch {
player1Touch = nil
} else if touch == player2Touch {
player2Touch = nil
}
}
}
}
struct GameState {
var prevT = CGFloat(0)
var player1Score = 0
var player2Score = 0
var ballVelocity = CGVector.zero
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment