diff options
Diffstat (limited to 'assets/scripts')
| -rw-r--r-- | assets/scripts/local2P.lua | 282 | ||||
| -rw-r--r-- | assets/scripts/mainMenu.lua | 26 |
2 files changed, 262 insertions, 46 deletions
diff --git a/assets/scripts/local2P.lua b/assets/scripts/local2P.lua index 7fd2efa..61262b2 100644 --- a/assets/scripts/local2P.lua +++ b/assets/scripts/local2P.lua @@ -1,18 +1,25 @@ ---@diagnostic disable: undefined-global backgrounds = require("assets.backgrounds.backgrounds-data") +sprite_height = 128 +sprite_width = 64 + +deltaTimeMultiplier = 60 groundTiles = { - { x = 250, y = HEIGHT - 300, width = 200, height = 30 }, - { x = WIDTH - 250 - 200, y = HEIGHT - 300, width = 200, height = 30 }, + { x = 250, y = HEIGHT - 300, width = 200, height = 30 }, + { x = WIDTH - 250 - 200, y = HEIGHT - 300, width = 200, height = 30 }, + { x = 0, y = HEIGHT - 100, width = WIDTH, height = 100 } } function SafeInitCharacter(character, default_x, default_y) - character.x = character.x or default_x - character.y = character.y or default_y - character.y_velocity = character.y_velocity or 1 + character.x = default_x + character.x_velocity = 1 + character.y = default_y + character.y_velocity = 1 character.current_sprite = character.asset_dir .. "/sprites/idle.png" + character.default_sprite = character.current_sprite character.can_jump = false character.knockback_counter = 0 character.combo_chain = 0 @@ -36,32 +43,88 @@ end function IsOnGround(character) for _, tile in ipairs(groundTiles) do - local characterFeetY = character.y + 128 + local characterFeetY = character.y + sprite_height - local isWithinX = character.x + 64 > tile.x and character.x < tile.x + tile.width + local isWithinX = character.x + sprite_width > tile.x and character.x < tile.x + tile.width local isTouchingY = characterFeetY >= tile.y and characterFeetY <= tile.y + tile.height + local isFalling = character.y_velocity >= 0 + + if isWithinX and isTouchingY and isFalling then + character.y = tile.y - sprite_height + return true + end + end + return false +end + +function IsHittingCeiling(character) + for _, tile in ipairs(groundTiles) do + local characterHeadY = character.y + local isWithinX = character.x + sprite_width > tile.x and character.x < tile.x + tile.width + local isTouchingY = characterHeadY <= tile.y + tile.height and characterHeadY >= tile.y if isWithinX and isTouchingY then - character.y = tile.y - 128 + character.y = tile.y + tile.height + character.y_velocity = 0 return true end end return false end +function IsTouchingWall(character, direction) + for _, tile in ipairs(groundTiles) do + local charBottom = character.y + sprite_height + local charTop = character.y + local tileBottom = tile.y + tile.height + local tileTop = tile.y + + local verticalOverlap = charBottom > tileTop and charTop < tileBottom + + if direction == "left" then + local nextX = character.x - character.speed + local willCollide = nextX < tile.x + tile.width and character.x >= tile.x + tile.width + + if willCollide and verticalOverlap then + character.x = tile.x + tile.width + return true + end + elseif direction == "right" then + local nextX = character.x + sprite_width + character.speed + local willCollide = nextX > tile.x and character.x + sprite_width <= tile.x + + if willCollide and verticalOverlap then + character.x = tile.x - sprite_width + return true + end + end + end + return false +end + function HandleP1Input() if Input.isKeyPressedOnce("W") and player1Character.can_jump then - player1Character.y_velocity = player1Character.jump_strength * -1.0 - player1Character.can_jump = false + player1Character.y_velocity = player1Character.jump_strength * -1.0 + player1Character.can_jump = false end + if Input.isKeyDown("D") then - player1Character.x = player1Character.x + player1Character.speed + if not IsTouchingWall(player1Character, "right") then + player1Character.x_velocity = player1Character.speed + else + player1Character.x_velocity = 0 + end end if Input.isKeyDown("A") then - player1Character.x = player1Character.x - player1Character.speed + if not IsTouchingWall(player1Character, "left") then + player1Character.x_velocity = -player1Character.speed + else + player1Character.x_velocity = 0 + end end + if Input.isKeyPressedOnce("F") then - + PerformPunch(player1Character, player2Character) end end @@ -70,46 +133,28 @@ function HandleP2Input() player2Character.y_velocity = player2Character.jump_strength * -1.0 player2Character.can_jump = false end + if Input.isKeyDown("RIGHT") then - player2Character.x = player2Character.x + player2Character.speed + if not IsTouchingWall(player2Character, "right") then + player2Character.x_velocity = player2Character.speed + else + player2Character.x_velocity = 0 + end end if Input.isKeyDown("LEFT") then - player2Character.x = player2Character.x - player2Character.speed - end -end - -function Update() - -- P1 physics - player1Character.y_velocity = player1Character.y_velocity + gravity - player1Character.y = player1Character.y + player1Character.y_velocity - - if IsOnGround(player1Character) then - player1Character.y_velocity = 0 - player1Character.can_jump = true + if not IsTouchingWall(player2Character, "left") then + player2Character.x_velocity = -player2Character.speed + else + player2Character.x_velocity = 0 + end end - -- P2 physics - player2Character.y_velocity = player2Character.y_velocity + gravity - player2Character.y = player2Character.y + player2Character.y_velocity - - if IsOnGround(player2Character) then - player2Character.y_velocity = 0 - player2Character.can_jump = true + if Input.isKeyPressedOnce("Right Alt") or Input.isKeyPressedOnce("Right Option") then + PerformPunch(player2Character, player1Character) end +end - -- Render - queueTextureForRender( - player1Character.current_sprite, - math.floor(player1Character.x), - math.floor(player1Character.y) - ) - - queueTextureForRender( - player2Character.current_sprite, - math.floor(player2Character.x), - math.floor(player2Character.y) - ) - +function DrawUI() local fontFile = "assets/fonts/OpenSans-Bold.ttf" local fontSize = 24 local text = player1Character.name @@ -144,10 +189,155 @@ function Update() local x = WIDTH - textWidth - 40 queueTextForRender(text, fontFile, x, y, fontSize, 0, 0, 0, 255) +end + +function Respawn(character) + SafeInitCharacter(character, 250, 150) +end + +function ApplyKnockback(attacker, target) + local knockbackMultiplierX = 0.47 + local knockbackMultiplierY = 0.01 + target.y_velocity = -10 - (target.knockback_counter * knockbackMultiplierY) + + local direction = 1 + if target.x < attacker.x then + direction = -1 + end + target.x_velocity = target.knockback_counter * knockbackMultiplierX * direction + -- target.x = target.x + direction * (target.knockback_counter * 0.7) +end + +function ApplyMinimalKnockback(attacker, target) + local knockbackMultiplierX = 0.47 + local knockbackMultiplierY = 0.01 + local knockbackCountMinimal = 5 + target.y_velocity = -10 - (knockbackCountMinimal * knockbackMultiplierY) + + local direction = 1 + if target.x < attacker.x then + direction = -1 + end + + target.x_velocity = knockbackCountMinimal * knockbackMultiplierX * direction + -- target.x = target.x + direction * (target.knockback_counter * 0.7) +end + +function KillPlayer(character) + character.lives = character.lives - 1 + character.knockback_counter = 0 + character.combo_chain = 0 + if character.lives > 0 then + Respawn(character) + end +end + +function RegisterHit(attacker, target, damage) + target.knockback_counter = target.knockback_counter + damage + attacker.combo_chain = attacker.combo_chain + 1 + + if attacker.combo_chain >= 4 then + ApplyKnockback(attacker, target) + attacker.combo_chain = 0 + else + ApplyMinimalKnockback(attacker, target) + end + + if target.knockback_counter >= 1000 then + KillPlayer(target) + end +end + +function PerformPunch(attacker, target) + local punch_range = 27 + local punch_height = 80 + + -- Determine direction of target relative to attacker + local punch_direction = (target.x > attacker.x) and "right" or "left" + + -- Set punch sprite + attacker.current_sprite = attacker.asset_dir .. "/sprites/punch_" .. punch_direction .. ".png" + + -- Reset sprite after a short delay (e.g., 0.15s) + Timer.clearAllTimers() + Timer.after(0.15, function() + attacker.current_sprite = attacker.default_sprite + end) + + -- Define hitbox based on punch direction + local hitbox = { + x = attacker.x + (punch_direction == "right" and sprite_width or -punch_range), + y = attacker.y + (sprite_height / 2) - (punch_height / 2), + width = punch_range, + height = punch_height + } + + local targetHitbox = { + x = target.x, + y = target.y, + width = sprite_width, + height = sprite_height + } + + local function isColliding(a, b) + return a.x < b.x + b.width and + a.x + a.width > b.x and + a.y < b.y + b.height and + a.y + a.height > b.y + end + + if isColliding(hitbox, targetHitbox) then + RegisterHit(attacker, target, attacker.hit_strength) + end +end + +function ApplyPhysics(character) + local deltaTimeMultiplier = 60 -- Target 60FPS + character.y_velocity = character.y_velocity + gravity * deltaTime * deltaTimeMultiplier + character.y = character.y + character.y_velocity * deltaTime * deltaTimeMultiplier + character.x = character.x + character.x_velocity * deltaTime * deltaTimeMultiplier + character.x_velocity = character.x_velocity * 0.99 + + if character.y_velocity > 0 then + -- Falling + if IsOnGround(character) then + character.y_velocity = 0 + character.can_jump = true + end + elseif character.y_velocity < 0 then + -- Going upward + IsHittingCeiling(character) + end + + if not IsOnGround(character) then + character.can_jump = false + end + + if character.y > HEIGHT + 50 then + KillPlayer(character) + end +end + +function Update() + -- Apply physics + ApplyPhysics(player1Character) + ApplyPhysics(player2Character) + + -- Render characters + queueTextureForRender(player1Character.current_sprite, math.floor(player1Character.x), math.floor(player1Character.y)) + queueTextureForRender(player2Character.current_sprite, math.floor(player2Character.x), math.floor(player2Character.y)) + + -- Environment DrawGroundTiles() -- Input HandleP1Input() HandleP2Input() + + -- UI + DrawUI() + + -- Timer + Timer.update(deltaTime) end diff --git a/assets/scripts/mainMenu.lua b/assets/scripts/mainMenu.lua index 05272af..4854775 100644 --- a/assets/scripts/mainMenu.lua +++ b/assets/scripts/mainMenu.lua @@ -22,6 +22,32 @@ Input = { end } +Timer = { + timers = {} +} + +function Timer.after(delay, callback) + table.insert(Timer.timers, { + time = delay, + action = callback + }) +end + +function Timer.clearAllTimers() + Timer.timers = {} +end + +function Timer.update(dt) + for i = #Timer.timers, 1, -1 do + local t = Timer.timers[i] + t.time = t.time - dt + if t.time <= 0 then + t.action() + table.remove(Timer.timers, i) + end + end +end + function Setup() setBgImage("assets/backgrounds/city-background-1.png") end |
