From f199da790d0f4d916398a647eebeb843fe20f988 Mon Sep 17 00:00:00 2001 From: Humza Shahid Date: Tue, 31 Dec 2024 10:04:40 +0000 Subject: [PATCH] add ability to charge for attack --- fcore/game-type.sml | 8 +-- fcore/game-update.sml | 40 +++++++-------- fcore/player.sml | 114 +++++++++++++++++++----------------------- shell/input-state.sml | 6 +++ 4 files changed, 81 insertions(+), 87 deletions(-) diff --git a/fcore/game-type.sml b/fcore/game-type.sml index 99c34b8..c65ff5a 100644 --- a/fcore/game-type.sml +++ b/fcore/game-type.sml @@ -19,7 +19,7 @@ sig datatype facing = FACING_LEFT | FACING_RIGHT - datatype main_attack = MAIN_NOT_ATTACKING | MAIN_ATTACKING of int + datatype main_attack = MAIN_NOT_ATTACKING | MAIN_ATTACKING | MAIN_CHARGING type defeated_enemies = {x: int, y: int} @@ -50,8 +50,8 @@ sig | W_X of int | W_Y of int | W_JUMP_PRESSED of bool - | W_MAIN_ATTACK_PRESSED of bool | W_ENEMIES of defeated_enemies vector + | W_CHARGE of int type enemy = {id: int, health: int, x: int, y: int} @@ -90,7 +90,7 @@ struct datatype facing = FACING_LEFT | FACING_RIGHT - datatype main_attack = MAIN_NOT_ATTACKING | MAIN_ATTACKING of int + datatype main_attack = MAIN_NOT_ATTACKING | MAIN_ATTACKING | MAIN_CHARGING type defeated_enemies = {x: int, y: int} @@ -121,8 +121,8 @@ struct | W_X of int | W_Y of int | W_JUMP_PRESSED of bool - | W_MAIN_ATTACK_PRESSED of bool | W_ENEMIES of defeated_enemies vector + | W_CHARGE of int type enemy = {id: int, health: int, x: int, y: int} diff --git a/fcore/game-update.sml b/fcore/game-update.sml index f55885d..9625348 100644 --- a/fcore/game-update.sml +++ b/fcore/game-update.sml @@ -79,7 +79,26 @@ struct val size = Player.size in case mainAttack of - MAIN_NOT_ATTACKING => + MAIN_ATTACKING => + let + (* when attacking, player collision should be larger than player themselves *) + val x = x - Player.halfSize + val y = y - Player.halfSize + val size = size * 2 + + val enemyCollisions = QuadTree.getCollisions + (x, y, size, size, 0, 0, 1920, 1080, 0, enemyTree) + val patches = + checkEnemiesWhileAttacking (player, enemies, enemyCollisions, []) + val player = Player.withPatches (player, patches) + + val enemyCollisions = Vector.fromList enemyCollisions + val enemies = filterEnemyCollisions + (Vector.length enemies - 1, enemyCollisions, enemies, []) + in + (player, enemies) + end + | _ => (case attacked of NOT_ATTACKED => let @@ -117,25 +136,6 @@ struct in (player, enemies) end) - | MAIN_ATTACKING amt => - let - (* when attacking, player collision should be larger than player themselves *) - val x = x - Player.halfSize - val y = y - Player.halfSize - val size = size * 2 - - val enemyCollisions = QuadTree.getCollisions - (x, y, size, size, 0, 0, 1920, 1080, 0, enemyTree) - val patches = - checkEnemiesWhileAttacking (player, enemies, enemyCollisions, []) - val player = Player.withPatches (player, patches) - - val enemyCollisions = Vector.fromList enemyCollisions - val enemies = filterEnemyCollisions - (Vector.length enemies - 1, enemyCollisions, enemies, []) - in - (player, enemies) - end end fun update (game, input) = diff --git a/fcore/player.sml b/fcore/player.sml index c6e0fb5..c343dce 100644 --- a/fcore/player.sml +++ b/fcore/player.sml @@ -211,7 +211,7 @@ struct , enemies , charge ) - | W_MAIN_ATTACK_PRESSED mainAttackPressed => + | W_ENEMIES enemies => mkPlayer ( health , xAxis @@ -227,7 +227,7 @@ struct , enemies , charge ) - | W_ENEMIES enemies => + | W_CHARGE charge => mkPlayer ( health , xAxis @@ -268,7 +268,6 @@ struct val floatLimit = 3 val recoilLimit = 15 val attackedLimit = 55 - val mainAttackLimit = 15 val maxCharge = 60 (* helper functions checking input *) @@ -476,68 +475,48 @@ struct end end - fun getMainAttackPatches (prevAttack, attackHeld, mainAttackPressed) = - case prevAttack of - MAIN_NOT_ATTACKING => - if attackHeld andalso not mainAttackPressed then MAIN_ATTACKING 0 - else prevAttack - | MAIN_ATTACKING amt => - if amt = mainAttackLimit then MAIN_NOT_ATTACKING - else let val amt = amt + 1 in MAIN_ATTACKING amt end + fun getMainAttackPatches (attackHeld, chargeHeld, charge) = + if attackHeld andalso charge > 0 then MAIN_ATTACKING + else if chargeHeld andalso not attackHeld then MAIN_CHARGING + else MAIN_NOT_ATTACKING fun getInputPatches (player: player, input) = - case #mainAttack player of - MAIN_NOT_ATTACKING => - let - val - { x - , y - , yAxis - , jumpPressed - , facing - , mainAttack - , mainAttackPressed - , ... - } = player + let + val + { x + , y + , yAxis + , jumpPressed + , facing + , mainAttack + , mainAttackPressed + , charge + , ... + } = player - val {leftHeld, rightHeld, upHeld, downHeld, attackHeld} = input + val {leftHeld, rightHeld, upHeld, downHeld, attackHeld, chargeHeld} = + input - val xAxis = getXAxis (leftHeld, rightHeld) - val facing = getFacing (facing, xAxis) - val mainAttack = - getMainAttackPatches (mainAttack, attackHeld, mainAttackPressed) + val xAxis = getXAxis (leftHeld, rightHeld) + val facing = getFacing (facing, xAxis) + val mainAttack = getMainAttackPatches (attackHeld, chargeHeld, charge) - val mainAttackPressed = - case mainAttack of - MAIN_ATTACKING _ => true - | _ => attackHeld + val charge = + case mainAttack of + MAIN_CHARGING => Int.min (charge + 1, maxCharge) + | MAIN_ATTACKING => Int.max (charge - 1, 0) + | MAIN_NOT_ATTACKING => charge - val acc = - [ W_X_AXIS xAxis - , W_FACING facing - , W_MAIN_ATTACK mainAttack - , W_MAIN_ATTACK_PRESSED mainAttackPressed - ] - val acc = getJumpPatches (player, upHeld, downHeld, acc) - in - acc - end - | MAIN_ATTACKING _ => - let - val {mainAttack, mainAttackPressed, ...} = player - val {attackHeld, ...} = input - val mainAttack = - getMainAttackPatches (mainAttack, attackHeld, mainAttackPressed) - val mainAttackPressed = - case mainAttack of - MAIN_ATTACKING _ => true - | _ => mainAttackPressed - in - [ W_X_AXIS STAY_STILL - , W_MAIN_ATTACK mainAttack - , W_MAIN_ATTACK_PRESSED mainAttackPressed - ] - end + val acc = + [ W_X_AXIS xAxis + , W_FACING facing + , W_MAIN_ATTACK mainAttack + , W_CHARGE charge + ] + val acc = getJumpPatches (player, upHeld, downHeld, acc) + in + acc + end fun getRecoilPatches player = case #recoil player of @@ -631,7 +610,16 @@ struct Block.lerp (x, y, size, size, width, height, 0.9, 0.9, 0.9) else Block.lerp (x, y, size, size, width, height, 0.5, 0.5, 0.5)) - | MAIN_ATTACKING _ => + | MAIN_ATTACKING => + (case attacked of + NOT_ATTACKED => + Block.lerp (x, y, size, size, width, height, 1.0, 0.5, 0.5) + | ATTACKED amt => + if amt mod 5 = 0 then + Block.lerp (x, y, size, size, width, height, 1.0, 0.9, 0.9) + else + Block.lerp (x, y, size, size, width, height, 1.0, 0.5, 0.5)) + | MAIN_CHARGING => (case attacked of NOT_ATTACKED => Block.lerp (x, y, size, size, width, height, 1.0, 0.5, 0.5) @@ -682,7 +670,7 @@ struct fun getFieldVec (player: player, width, height) = case #mainAttack player of MAIN_NOT_ATTACKING => Vector.fromList [] - | MAIN_ATTACKING amt => + | _ => let val {x, y, ...} = player val wratio = width / 1920.0 @@ -700,7 +688,7 @@ struct val y = (Real32.fromInt y - halfRealSize) * wratio + yOffset val realSize = (realSize * 2.0) * wratio - val alpha = Real32.fromInt amt / Real32.fromInt mainAttackLimit + val alpha = 1.0 in Field.lerp (x, y, realSize, realSize, width, height, 0.7, 0.7, 1.0, alpha) @@ -717,7 +705,7 @@ struct val y = (Real32.fromInt y - halfRealSize) * hratio val realSize = (realSize * 2.0) * hratio - val alpha = Real32.fromInt amt / Real32.fromInt mainAttackLimit + val alpha = 1.0 in Field.lerp (x, y, realSize, realSize, width, height, 0.7, 0.7, 1.0, alpha) diff --git a/shell/input-state.sml b/shell/input-state.sml index 09dcab0..9809f27 100644 --- a/shell/input-state.sml +++ b/shell/input-state.sml @@ -7,6 +7,7 @@ struct , upHeld = ref false , downHeld = ref false , attackHeld = ref false + , chargeHeld = ref false , width = ref (1920.0 : Real32.real) , height = ref (1080.0 : Real32.real) } @@ -17,6 +18,7 @@ struct , upHeld = !(#upHeld state) , downHeld = !(#downHeld state) , attackHeld = !(#attackHeld state) + , chargeHeld = !(#chargeHeld state) } fun getWidth () = @@ -51,6 +53,10 @@ struct if action = PRESS then (#attackHeld state) := true else if action = RELEASE then (#attackHeld state) := false else () + else if key = KEY_L then + if action = PRESS then (#chargeHeld state) := true + else if action = RELEASE then (#chargeHeld state) := false + else () else ()