package main import "core:math" import "core:math/linalg" import rl "vendor:raylib" Ball :: struct { position: Vec2, velocity: Vec2, pad_offset: Vec2, angular_velocity: f32, radius: f32, is_on_pad: bool, } ball_update :: proc(ball: ^Ball, game: ^Game, delta: f32) -> bool { using game if ball.is_on_pad { ball.position = pad.position + ball.pad_offset } else { ball_position_prev := ball.position ball.velocity = rl.Vector2Rotate(ball.velocity, ball.angular_velocity * delta) if abs(ball.velocity.y) < 100 && ball.angular_velocity == 0 { ball.velocity.y += math.sign(ball.velocity.y) * 100 * delta } ball.position += ball.velocity * delta if ball.position.y < GameField.y { if ball.position.x < ball.radius { ball.position.x = ball.radius ball.velocity.x = -ball.velocity.x ball.angular_velocity = 0 } if ball.position.x > GameField.x - ball.radius { ball.position.x = GameField.x - ball.radius ball.velocity.x = -ball.velocity.x ball.angular_velocity = 0 } } else { return false } if ball.position.y < ball.radius { ball.position.y = ball.radius ball.velocity.y = -ball.velocity.y ball.angular_velocity = 0 } if ball.position.y + ball.radius > pad.position.y - pad.size.y / 2 && ball_position_prev.y + ball.radius < pad.position.y - pad.size.y / 2 && ball.position.x + ball.radius > pad.position.x - pad.size.x / 2 && ball.position.x - ball.radius < pad.position.x + pad.size.x / 2 { dir := Vec2{0, -1} offset_x := ball.position.x - pad.position.x dir.x = offset_x / (pad.size.x / 2) ball.velocity = rl.Vector2Normalize(dir) * rl.Vector2Length(ball.velocity) ball.angular_velocity = -pad.velocity.x / PAD_MAX_SPEED * math.PI / 3 } for &brick, i in bricks { if brick.is_flying { continue } clamped := Vec2 { clamp( ball.position.x, brick.position.x - brick.size.x / 2, brick.position.x + brick.size.x / 2, ), clamp( ball.position.y, brick.position.y - brick.size.y / 2, brick.position.y + brick.size.y / 2, ), } diff := clamped - ball.position normal := rl.Vector2Normalize(-diff) if rl.Vector2LengthSqr(diff) < ball.radius * ball.radius { if brick.type != .SOLID{ brick.hits -= 1 } if brick.hits <= 0 && !brick.is_flying { brick.is_flying = true brick.velocity = ball.velocity / 2 brick.angular_velocity = brick.velocity.x game.score += brick.score } if brick.hit_callback != nil { brick.hit_callback(&brick, game) } ball.position = clamped + normal * ball.radius ball.velocity = linalg.reflect(ball.velocity, normal) ball.angular_velocity = 0 } } } return true } ball_draw :: proc(ball: ^Ball) { draw_ball_virtual(ball.position, ball.radius) } draw_ball_virtual :: proc(position: Vec2, radius: f32) { rl.DrawCircleV(position, radius, rl.Color{80, 120, 255, 255}) rl.DrawCircleV(position - radius / 3, radius / 5, rl.Color{80, 160, 255, 255}) }