package main import rl "vendor:raylib" import "core:fmt" Brick_Type :: enum { NORMAL, EXPLOSIVE, BONUS, HARD, SOLID } brick_names := [Brick_Type]cstring { .NORMAL = "обычный", .EXPLOSIVE = "взрывной", .BONUS = "восстанавливает здоровье", .HARD = "крепкий", .SOLID = "нерушимый" } brick_colors := [Brick_Type]rl.Color { .NORMAL = rl.Color{190, 190, 190, 255}, .EXPLOSIVE = rl.Color{250, 30, 30, 255}, .BONUS = rl.Color{30, 250, 30, 255}, .HARD = rl.Color{190, 190, 255, 255}, .SOLID = rl.Color{80, 80, 100, 255} } brick_scores := [Brick_Type]u32 { .NORMAL = 100, .HARD = 500, .BONUS = 1000, .EXPLOSIVE = 1000, .SOLID = 0, } brick_hits := [Brick_Type]i32 { .NORMAL = 1, .EXPLOSIVE = 1, .BONUS = 1, .HARD = 2, .SOLID = 10000000 } BrickHitCallback :: proc(brick: ^Brick, game: ^Game) brick_callbacks := [Brick_Type]BrickHitCallback { .NORMAL = nil, .EXPLOSIVE = brick_explode, .BONUS = nil, .HARD = nil, .SOLID = nil } Brick :: struct { position: Vec2, velocity: Vec2, size: Vec2, angle: f32, angular_velocity: f32, is_flying: bool, is_fixed: bool, color: rl.Color, hits: i32, is_to_free: bool, type: Brick_Type, score: u32, hit_callback: proc(brick: ^Brick, game: ^Game) } spawn_brick :: proc(position: Vec2, size: Vec2, type: Brick_Type = Brick_Type.NORMAL) -> Brick { return Brick { position = position, velocity = Vec2{}, size = size, is_flying = false, is_fixed = true, type = type, color = brick_colors[type], hits = brick_hits[type], score = brick_scores[type], hit_callback = brick_callbacks[type], angle = 0 } } brick_update :: proc(brick: ^Brick, game: ^Game, delta: f32) { if !brick.is_flying { return } brick.velocity.y += 500 * delta brick.position += brick.velocity * delta brick.angle += brick.angular_velocity * delta screen_pos := rl.GetWorldToScreen2D(brick.position, game.camera) if brick.position.x < brick.size.x / 2 { brick.position.x = brick.size.x / 2 brick.velocity.x = -brick.velocity.x } if brick.position.x > GameField.x - brick.size.x / 2 { brick.position.x = GameField.x - brick.size.x / 2 brick.velocity.x = -brick.velocity.x } if rl.CheckCollisionCircleRec(brick.position, brick.size.x / 2, rl.Rectangle{ game.pad.position.x - game.pad.size.x / 2, game.pad.position.y - game.pad.size.y / 2, game.pad.size.x, game.pad.size.y }) { if brick.type != .BONUS { game.pad.health -= 30 } else { game.pad.health = min(game.pad.health + 30, 100) } brick.is_to_free = true } if !rl.CheckCollisionRecs(rl.Rectangle{screen_pos.x - brick.size.x / 2, screen_pos.y - brick.size.y / 2, brick.size.x, brick.size.y}, rl.Rectangle{0, 0, WINDOWF.x, WINDOWF.y} ) { brick.is_to_free = true } } brick_draw :: proc(brick: ^Brick) { rl.DrawRectanglePro( rl.Rectangle{brick.position.x, brick.position.y, brick.size.x, brick.size.y}, brick.size / 2, brick.angle, brick.color ) if brick.type == .HARD && brick.hits <= 1 { rl.DrawRectanglePro( rl.Rectangle{brick.position.x, brick.position.y, brick.size.x / 1.5, brick.size.y / 1.5}, brick.size / 3, brick.angle, rl.ColorTint(brick.color, rl.Color{180, 180, 180, 255}) ) } } brick_explode :: proc(brick: ^Brick, game: ^Game) { radius := brick.size.x * 2 brick.is_to_free = true explode(brick.position, radius, 0.4) for &other, i in game.bricks { if other.is_to_free { continue } if &other == brick { continue } diff := other.position - brick.position dir := rl.Vector2Normalize(diff) dis := rl.Vector2Length(diff) if dis > radius { continue } switch other.type { case .NORMAL, .HARD, .SOLID: other.hits = 0 other.is_flying = true other.velocity += dir * (radius - dis + 50) * 3 other.angular_velocity = other.velocity.x * 2 game.score += other.score case .EXPLOSIVE, .BONUS: if other.hit_callback != nil { other.hit_callback(&other, game) } } } }