Basic combat
This commit is contained in:
parent
31a0bd9a34
commit
0b164302c4
7 changed files with 636 additions and 55 deletions
76
README.org
76
README.org
|
|
@ -15,61 +15,31 @@ Once both of those dependencies are installed, run:
|
||||||
./bitter-duel
|
./bitter-duel
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
* Design & Gameplay
|
* How To Play
|
||||||
|
First to 3 hits wins.
|
||||||
|
|
||||||
In Bitter Duel, you control a single character on a 5 by 5 grid. There is a single opponent facing off against you.
|
You are blue.
|
||||||
|
|
||||||
Each character has a stance and hand position, and can move, attack, or assume a stance on their turn.
|
Each unit on the board has a stance and a hand position.
|
||||||
Each character has 3 health.
|
|
||||||
|
The stance can be high, mid, or low. You can change your stance each turn.
|
||||||
|
|
||||||
|
Hand position can be high-right, high-left, mid-right, mid-left, low-right, low-left --- forming a circle.
|
||||||
|
Each turn you can choose to attack from your current hand position, or from an adjacent one on the circle.
|
||||||
|
For example, from high-right, you can attack from high-right, high-left, or mid-right.
|
||||||
|
After the attack, your hand moves to the opposite position.
|
||||||
|
For example, attacking from high-right, your hand becomes low-left.
|
||||||
|
|
||||||
|
You can move 1 square on each turn.
|
||||||
|
|
||||||
|
Build your order: move, change stance, and attack.
|
||||||
|
|
||||||
|
Orders are submitted simultaneously and then resolved: movement first, then stance change, then attack if in range (neighboring squares).
|
||||||
|
|
||||||
** Stances
|
** Stances
|
||||||
Stances are initial striking positions, and provide some intrinsic bonus offense and defense on the turn that the stance is assumed.
|
Your chance to hit is higher if your attack matches your stance. A mid-right attack has a lower chance of hidding from a high stance than a high-right attack.
|
||||||
|
|
||||||
After attacking or moving, your stance is broken until you next assume it.
|
Your stance also determines your defense.
|
||||||
|
A high stance has bonus defense against high attacks, but weak defense against low attacks.
|
||||||
There are 4 stances:
|
A low stance is the opposite.
|
||||||
- High (Up-Left/Up-Right)
|
A mid stance has bonus defense against mid attacks, but weak defense against high and low.
|
||||||
- The High stance has a higher defense (70) against High and (60) Stab attacks, but low defense against Low attacks (30).
|
|
||||||
- The High stance adds additional offense to your High attacks (80).
|
|
||||||
- Low (Down-Left/Down-Right)
|
|
||||||
- The Low stance has higher defense (70) against Low and (60) Stab attacks, but low defense against High attacks (30).
|
|
||||||
- The low stance adds additional offense to your Low attacks (70).
|
|
||||||
- Side (Mid-Left/Mid-Right)
|
|
||||||
- The Side stance has higher defense (70) against swing attacks, but low defense (30) against High and Low attacks.
|
|
||||||
- The Side stance adds additional offense to your Swing attacks (70)
|
|
||||||
|
|
||||||
** Hand Position
|
|
||||||
Your hand position adds defense against attacks coming from that direction (60) and dictates what next attacks you can perform.
|
|
||||||
|
|
||||||
The hand positions are:
|
|
||||||
- Up-left:
|
|
||||||
- Defense against top and right attacks.
|
|
||||||
- Up-right
|
|
||||||
- Defense against top and left attacks.
|
|
||||||
- Mid-right
|
|
||||||
- Defense against mid and left attacks.
|
|
||||||
- Mid-left
|
|
||||||
- Defense against mid and right attacks.
|
|
||||||
- Down-left
|
|
||||||
- Defense against bottom and right attacks.
|
|
||||||
- Down-right
|
|
||||||
- Defense against bottom and left attacks.
|
|
||||||
|
|
||||||
** Attacks
|
|
||||||
Each of the hand positions is also a type of attack. You may perform an attack from the 3 positions near the hand position.
|
|
||||||
For example, Up-Left can attack from Up-Left, Up-Right, or Mid-Left.
|
|
||||||
After an attack, your hand position changes to the opposite of the attack. So Up-Left becomes Down-Right.
|
|
||||||
|
|
||||||
** Attacking and Turns
|
|
||||||
Both players lock in their actions, then the turn is resolved like so:
|
|
||||||
1. Handle any stance changes
|
|
||||||
2. Handle any movement.
|
|
||||||
3. Resolve attacks.
|
|
||||||
|
|
||||||
To resolve an attack, get the offense of the attack and defense for that attack from the defender.
|
|
||||||
Subtract Defense from Offense, divide by 10, and add 5. Call this the "target number".
|
|
||||||
Roll a number between 1 and 10. If the roll is lower than the target number, the attack goes through and the defender takes a hit.
|
|
||||||
Characters always attack and defend from the hand position they start in at the beginning of the turn.
|
|
||||||
|
|
||||||
* Credits
|
|
||||||
- https://sethbb.itch.io/32rogues
|
|
||||||
|
|
|
||||||
143
modules/attack.scm
Normal file
143
modules/attack.scm
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
(module (bd attack) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
(chicken module)
|
||||||
|
(chicken string)
|
||||||
|
(bd random)
|
||||||
|
(srfi 99))
|
||||||
|
|
||||||
|
(export hand-direction hand-vert hand-horiz)
|
||||||
|
(define-record-type <hand-direction>
|
||||||
|
(hand-direction vert horiz)
|
||||||
|
hand-direction?
|
||||||
|
(vert hand-vert)
|
||||||
|
(horiz hand-horiz))
|
||||||
|
|
||||||
|
(export direction-to-string)
|
||||||
|
(define (direction-to-string dir)
|
||||||
|
(conc (hand-vert dir)
|
||||||
|
" : "
|
||||||
|
(hand-horiz dir)))
|
||||||
|
|
||||||
|
(define (opposite-horiz h)
|
||||||
|
(if (eqv? h 'right)
|
||||||
|
'left
|
||||||
|
'right))
|
||||||
|
|
||||||
|
(define (opposite-vert v)
|
||||||
|
(cond
|
||||||
|
((eqv? v 'high) 'low)
|
||||||
|
((eqv? v 'mid) 'mid)
|
||||||
|
((eqv? v 'low) 'high)))
|
||||||
|
|
||||||
|
(export opposite-pos)
|
||||||
|
(define (opposite-pos h)
|
||||||
|
(hand-direction
|
||||||
|
(opposite-vert (hand-vert h))
|
||||||
|
(opposite-horiz (hand-horiz h))))
|
||||||
|
|
||||||
|
(define (pos-= h1 h2)
|
||||||
|
(and (eqv? (hand-vert h1) (hand-vert h2))
|
||||||
|
(eqv? (hand-horiz h1) (hand-horiz h2))))
|
||||||
|
|
||||||
|
(define (pos-to-int h)
|
||||||
|
(cond
|
||||||
|
((pos-= h (hand-direction 'high 'right)) 0)
|
||||||
|
((pos-= h (hand-direction 'high 'left)) 1)
|
||||||
|
((pos-= h (hand-direction 'mid 'left)) 2)
|
||||||
|
((pos-= h (hand-direction 'low 'left)) 3)
|
||||||
|
((pos-= h (hand-direction 'low 'right)) 4)
|
||||||
|
((pos-= h (hand-direction 'mid 'right)) 5)))
|
||||||
|
|
||||||
|
(define (int-to-pos i)
|
||||||
|
(case i
|
||||||
|
((0) (hand-direction 'high 'right))
|
||||||
|
((1) (hand-direction 'high 'left))
|
||||||
|
((2) (hand-direction 'mid 'left))
|
||||||
|
((3) (hand-direction 'low 'left))
|
||||||
|
((4) (hand-direction 'low 'right))
|
||||||
|
((5) (hand-direction 'mid 'right))))
|
||||||
|
|
||||||
|
(export rotate-pos rotate-pos-cc)
|
||||||
|
(define (rotate-pos p)
|
||||||
|
(let ((pos (pos-to-int p)))
|
||||||
|
(if (= pos 5)
|
||||||
|
(int-to-pos 0)
|
||||||
|
(int-to-pos (+ 1 pos)))))
|
||||||
|
|
||||||
|
(define (rotate-pos-cc p)
|
||||||
|
(let ((pos (pos-to-int p)))
|
||||||
|
(if (= pos 0)
|
||||||
|
(int-to-pos 5)
|
||||||
|
(int-to-pos (- pos 1)))))
|
||||||
|
|
||||||
|
(export attack attack-direction attack-offense)
|
||||||
|
(define-record-type <attack>
|
||||||
|
(attack direction offense)
|
||||||
|
attack?
|
||||||
|
(direction attack-direction)
|
||||||
|
(offense attack-offense))
|
||||||
|
|
||||||
|
(define (high-stance-attack dir)
|
||||||
|
(if (eqv? 'high (hand-vert dir))
|
||||||
|
80
|
||||||
|
50))
|
||||||
|
|
||||||
|
(define (mid-stance-attack dir)
|
||||||
|
(if (eqv? 'mid (hand-vert dir))
|
||||||
|
80
|
||||||
|
50))
|
||||||
|
|
||||||
|
(define (low-stance-attack dir)
|
||||||
|
(if (eqv? 'low (hand-vert dir))
|
||||||
|
80
|
||||||
|
50))
|
||||||
|
|
||||||
|
(export attack-from-stance)
|
||||||
|
(define (attack-from-stance attack-direction stance)
|
||||||
|
(attack attack-direction
|
||||||
|
(cond
|
||||||
|
((eqv? stance 'high) (high-stance-attack attack-direction))
|
||||||
|
((eqv? stance 'mid) (mid-stance-attack attack-direction))
|
||||||
|
((eqv? stance 'low) (mid-stance-attack attack-direction))
|
||||||
|
(else 50))))
|
||||||
|
|
||||||
|
(define (high-stance-defense dir)
|
||||||
|
(cond
|
||||||
|
((eqv? 'high (hand-vert dir)) 20)
|
||||||
|
((eqv? 'low (hand-vert dir)) -30)
|
||||||
|
(else 0)))
|
||||||
|
|
||||||
|
(define (mid-stance-defense dir)
|
||||||
|
(cond
|
||||||
|
((eqv? 'mid (hand-vert dir)) 20)
|
||||||
|
(else -30)))
|
||||||
|
|
||||||
|
(define (low-stance-defense dir)
|
||||||
|
(cond
|
||||||
|
((eqv? 'low (hand-vert dir)) 20)
|
||||||
|
((eqv? 'high (hand-vert dir)) -30)
|
||||||
|
(else 0)))
|
||||||
|
|
||||||
|
(export defense-from-stance)
|
||||||
|
(define (defense-from-stance attack-dir hand-pos stance)
|
||||||
|
(+ 40
|
||||||
|
(if (or (eqv? (hand-vert attack-dir)
|
||||||
|
(opposite-vert (hand-vert hand-pos)))
|
||||||
|
(eqv? (hand-horiz attack-dir)
|
||||||
|
(opposite-horiz (hand-horiz hand-pos))))
|
||||||
|
20
|
||||||
|
0)
|
||||||
|
(cond
|
||||||
|
((eqv? stance 'high) (high-stance-defense attack-dir))
|
||||||
|
((eqv? stance 'mid) (mid-stance-defense attack-dir))
|
||||||
|
((eqv? stance 'low) (low-stance-defense attack-dir))
|
||||||
|
(else 0))))
|
||||||
|
|
||||||
|
(export resolve-combat)
|
||||||
|
(define (resolve-combat attack defense)
|
||||||
|
(let ((tn (+ 5 (/ (- (attack-offense attack) defense) 10))))
|
||||||
|
(if (> tn (+ 1 (rand-int 10)))
|
||||||
|
'hit
|
||||||
|
'miss)))
|
||||||
|
)
|
||||||
74
modules/grid.scm
Normal file
74
modules/grid.scm
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
(module (bd grid) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
(chicken module)
|
||||||
|
raylib
|
||||||
|
(imugi core)
|
||||||
|
(imugi drawing)
|
||||||
|
(imugi math)
|
||||||
|
(srfi 1)
|
||||||
|
(srfi 99))
|
||||||
|
|
||||||
|
(export grid)
|
||||||
|
(define (grid len wid default)
|
||||||
|
(define (iter i acc)
|
||||||
|
(if (= len i)
|
||||||
|
acc
|
||||||
|
(iter
|
||||||
|
(+ 1 i)
|
||||||
|
(cons (make-list wid default) acc))))
|
||||||
|
(iter 0 '()))
|
||||||
|
|
||||||
|
(export gv)
|
||||||
|
(define (gv grd x y)
|
||||||
|
(list-ref (list-ref grd y) x))
|
||||||
|
|
||||||
|
(export gv!)
|
||||||
|
(define (gv! grd x y val)
|
||||||
|
(set! (list-ref (list-ref grd y) x) val))
|
||||||
|
|
||||||
|
(define (draw-grid-square offset width x y entity)
|
||||||
|
(let ((square-pos (v+ offset
|
||||||
|
(vec (* x width)
|
||||||
|
(* y width)))))
|
||||||
|
(push-render-object
|
||||||
|
'screen
|
||||||
|
0
|
||||||
|
(lambda ()
|
||||||
|
(draw-rectangle-2d
|
||||||
|
square-pos
|
||||||
|
width
|
||||||
|
width
|
||||||
|
(cond
|
||||||
|
((eqv? entity 'player) (make-color 0 0 1 1))
|
||||||
|
((eqv? entity 'foe) (make-color 1 0 0 1))
|
||||||
|
(else (make-color 0 0 0 1)))
|
||||||
|
(not (eqv? entity 'none))
|
||||||
|
2)))))
|
||||||
|
|
||||||
|
(export draw-grid)
|
||||||
|
(define draw-grid
|
||||||
|
(make-system
|
||||||
|
'draw-grid
|
||||||
|
10
|
||||||
|
'entity
|
||||||
|
'(<grid-view>)
|
||||||
|
(lambda (_ grid-view)
|
||||||
|
(let ((gd (grid-view-grid grid-view))
|
||||||
|
(width (grid-view-width grid-view))
|
||||||
|
(pos (grid-view-pos grid-view)))
|
||||||
|
(do ((i 0 (+ 1 i)))
|
||||||
|
((= i (length gd)) gd)
|
||||||
|
(let ((row (list-ref gd i)))
|
||||||
|
(do ((j 0 (+ 1 j)))
|
||||||
|
((= j (length row)) row)
|
||||||
|
(draw-grid-square pos width i j (list-ref row j)))))))))
|
||||||
|
|
||||||
|
(export grid-view grid-view-grid)
|
||||||
|
(define-record-type <grid-view>
|
||||||
|
(grid-view start-pos gd width)
|
||||||
|
grid-view?
|
||||||
|
(start-pos grid-view-pos set-grid-view-pos!)
|
||||||
|
(gd grid-view-grid set-grid-view-grid!)
|
||||||
|
(width grid-view-width set-grid-view-width!))
|
||||||
|
)
|
||||||
15
modules/random.scm
Normal file
15
modules/random.scm
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
(module (bd random) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
(chicken module)
|
||||||
|
(chicken random))
|
||||||
|
|
||||||
|
(export random)
|
||||||
|
(export rand-int)
|
||||||
|
(define random pseudo-random-real)
|
||||||
|
(define rand-int pseudo-random-integer)
|
||||||
|
|
||||||
|
(export pick-random)
|
||||||
|
(define (pick-random lst)
|
||||||
|
(list-ref lst (rand-int (length lst))))
|
||||||
|
)
|
||||||
|
|
@ -29,6 +29,22 @@
|
||||||
(color label-color set-label-color!)
|
(color label-color set-label-color!)
|
||||||
(text label-text set-label-text!))
|
(text label-text set-label-text!))
|
||||||
|
|
||||||
|
(export process-dynamic-labels)
|
||||||
|
(define process-dynamic-labels
|
||||||
|
(make-system
|
||||||
|
'process-dynamic-labels
|
||||||
|
9
|
||||||
|
'entity
|
||||||
|
'(<label> <dynamic-label>)
|
||||||
|
(lambda (_ label d-label)
|
||||||
|
(set-label-text! label ((label-func d-label))))))
|
||||||
|
|
||||||
|
(export dynamic-label)
|
||||||
|
(define-record-type <dynamic-label>
|
||||||
|
(dynamic-label func)
|
||||||
|
dynamic-label?
|
||||||
|
(func label-func))
|
||||||
|
|
||||||
;; Title/subtitle/footer etc are basically just different styles
|
;; Title/subtitle/footer etc are basically just different styles
|
||||||
(export title)
|
(export title)
|
||||||
(define (title position text
|
(define (title position text
|
||||||
|
|
|
||||||
361
src/arena.scm
Normal file
361
src/arena.scm
Normal file
|
|
@ -0,0 +1,361 @@
|
||||||
|
(module (arena) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
(chicken module)
|
||||||
|
(chicken string)
|
||||||
|
(imugi core)
|
||||||
|
(imugi input)
|
||||||
|
(imugi scene)
|
||||||
|
(imugi math)
|
||||||
|
(bd ui)
|
||||||
|
(bd random)
|
||||||
|
(bd attack)
|
||||||
|
(bd grid)
|
||||||
|
(srfi 1)
|
||||||
|
(srfi 99))
|
||||||
|
|
||||||
|
(define battle-state 'active)
|
||||||
|
|
||||||
|
(define player 'player)
|
||||||
|
(define enemy 'foe)
|
||||||
|
(define empty 'none)
|
||||||
|
|
||||||
|
(define grid-size 5)
|
||||||
|
|
||||||
|
(define field (grid grid-size grid-size empty))
|
||||||
|
|
||||||
|
(define-record-type <unit>
|
||||||
|
(unit type health pos hand-pos stance)
|
||||||
|
unit?
|
||||||
|
(type unit-type)
|
||||||
|
(health unit-health set-unit-health!)
|
||||||
|
(pos unit-pos set-unit-pos!)
|
||||||
|
(hand-pos unit-hand-pos set-unit-hand-pos!)
|
||||||
|
(stance unit-stance set-unit-stance!))
|
||||||
|
|
||||||
|
(define player-unit
|
||||||
|
(unit
|
||||||
|
player
|
||||||
|
3
|
||||||
|
;; Place player
|
||||||
|
(vec (rand-int grid-size)
|
||||||
|
(rand-int grid-size))
|
||||||
|
(hand-direction 'mid 'right)
|
||||||
|
'mid))
|
||||||
|
|
||||||
|
(define enemy-unit
|
||||||
|
(unit
|
||||||
|
enemy
|
||||||
|
3
|
||||||
|
;; Place enemy
|
||||||
|
(let loop ()
|
||||||
|
(let ((p-x (rand-int grid-size))
|
||||||
|
(p-y (rand-int grid-size)))
|
||||||
|
(if (not (v= (vec p-x p-y)
|
||||||
|
(unit-pos player-unit)))
|
||||||
|
(vec p-x p-y)
|
||||||
|
(loop))))
|
||||||
|
(hand-direction 'mid 'left)
|
||||||
|
'mid))
|
||||||
|
|
||||||
|
(define-record-type <order>
|
||||||
|
(order movement attack stance)
|
||||||
|
order?
|
||||||
|
(movement order-mov set-order-mov!)
|
||||||
|
(attack order-atk set-order-atk!)
|
||||||
|
(stance order-stance set-order-stance!))
|
||||||
|
|
||||||
|
(define (empty-order)
|
||||||
|
(order #f
|
||||||
|
#f
|
||||||
|
#f))
|
||||||
|
|
||||||
|
(define player-order
|
||||||
|
(empty-order))
|
||||||
|
|
||||||
|
(define (possible-enemy-moves)
|
||||||
|
(filter
|
||||||
|
(lambda (p)
|
||||||
|
(let ((res (v+ p (unit-pos enemy-unit))))
|
||||||
|
(and (> 5 (v-x res) -1)
|
||||||
|
(> 5 (v-y res) -1))))
|
||||||
|
(list (vec 0 1)
|
||||||
|
(vec 0 -1)
|
||||||
|
(vec 1 0)
|
||||||
|
(vec -1 0))))
|
||||||
|
|
||||||
|
(define (distance-between-units)
|
||||||
|
(let* ((p-pos (unit-pos player-unit))
|
||||||
|
(e-pos (unit-pos enemy-unit))
|
||||||
|
(d-x (abs (- (v-x p-pos) (v-x e-pos))))
|
||||||
|
(d-y (abs (- (v-y p-pos) (v-y e-pos)))))
|
||||||
|
(+ d-x d-y)))
|
||||||
|
|
||||||
|
(define (enemy-order)
|
||||||
|
(let ((o (empty-order)))
|
||||||
|
;; Movement AI
|
||||||
|
(set-order-mov! o
|
||||||
|
(if (= 1 (unit-health enemy-unit))
|
||||||
|
(pick-random (possible-enemy-moves))
|
||||||
|
(if (and (< 0.4 (random))
|
||||||
|
(< 1 (distance-between-units)))
|
||||||
|
(pick-random (possible-enemy-moves))
|
||||||
|
#f)))
|
||||||
|
(when (< 0.5 (random))
|
||||||
|
(set-order-stance! o (pick-random '(high mid low))))
|
||||||
|
(set-order-atk!
|
||||||
|
o
|
||||||
|
(let ((roll (random)))
|
||||||
|
(cond
|
||||||
|
((> 0.6 roll) (unit-hand-pos enemy-unit))
|
||||||
|
((> 0.8 roll) (rotate-pos-cc (unit-hand-pos enemy-unit)))
|
||||||
|
(else (rotate-pos (unit-hand-pos enemy-unit))))))
|
||||||
|
o))
|
||||||
|
|
||||||
|
(define (attempt-attack attack-dir unit)
|
||||||
|
(display (unit-type unit))
|
||||||
|
(newline)
|
||||||
|
(let* ((target (if (eqv? (unit-type unit) player) enemy-unit player-unit))
|
||||||
|
(outcome (resolve-combat (attack-from-stance attack-dir (unit-stance unit))
|
||||||
|
(defense-from-stance attack-dir
|
||||||
|
(unit-hand-pos target)
|
||||||
|
(unit-stance unit)))))
|
||||||
|
(if (eqv? outcome 'hit)
|
||||||
|
(begin
|
||||||
|
(display (conc (unit-type unit) " hits!"))
|
||||||
|
(set-unit-health! target (- (unit-health target) 1))
|
||||||
|
(when (= 0 (unit-health target))
|
||||||
|
(set! battle-state 'ended)))
|
||||||
|
(display (conc (unit-type unit) " misses!")))
|
||||||
|
(newline)
|
||||||
|
(set-unit-hand-pos! unit (opposite-pos attack-dir))))
|
||||||
|
|
||||||
|
(define (move-unit unit pos)
|
||||||
|
(let ((target (if (eqv? (unit-type unit) player) enemy-unit player-unit)))
|
||||||
|
(unless (v= (unit-pos target) pos)
|
||||||
|
(set-unit-pos! unit pos))))
|
||||||
|
|
||||||
|
(define (apply-order order unit)
|
||||||
|
(when (order-mov order)
|
||||||
|
(move-unit unit (v+ (unit-pos unit) (order-mov order))))
|
||||||
|
(when (order-stance order)
|
||||||
|
(set-unit-stance! unit (order-stance order)))
|
||||||
|
(when (and (order-atk order)
|
||||||
|
(= 1 (distance-between-units)))
|
||||||
|
(attempt-attack (order-atk order) unit)))
|
||||||
|
|
||||||
|
(define update-grid-entities
|
||||||
|
(make-system
|
||||||
|
'update-grid-entities
|
||||||
|
0
|
||||||
|
'entity
|
||||||
|
'(<grid-view>)
|
||||||
|
(lambda (_ g)
|
||||||
|
(let ((gd (grid-view-grid g)))
|
||||||
|
(do ((i 0 (+ 1 i)))
|
||||||
|
((= i (length gd)) gd)
|
||||||
|
(let ((row (list-ref gd i)))
|
||||||
|
(do ((j 0 (+ 1 j)))
|
||||||
|
((= j (length row)) row)
|
||||||
|
(gv! gd j i (cond
|
||||||
|
((v= (unit-pos player-unit) (vec j i)) player)
|
||||||
|
((v= (unit-pos enemy-unit) (vec j i)) enemy)
|
||||||
|
(else empty))))))))))
|
||||||
|
|
||||||
|
(export arena)
|
||||||
|
(define (arena)
|
||||||
|
(scene
|
||||||
|
push-actions
|
||||||
|
process-dynamic-labels
|
||||||
|
update-grid-entities
|
||||||
|
draw-labels
|
||||||
|
draw-grid
|
||||||
|
handle-buttons
|
||||||
|
|
||||||
|
;; Level heading
|
||||||
|
(entity
|
||||||
|
(subtitle
|
||||||
|
(vec
|
||||||
|
0
|
||||||
|
10)
|
||||||
|
"Fight!"
|
||||||
|
centered: (cons #t #f)))
|
||||||
|
|
||||||
|
;; Grid view
|
||||||
|
(entity
|
||||||
|
(grid-view
|
||||||
|
(vec 190 100)
|
||||||
|
field
|
||||||
|
75))
|
||||||
|
|
||||||
|
;; Stance inputs
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 50
|
||||||
|
460)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"High Stance!")
|
||||||
|
(lambda ()
|
||||||
|
(set-order-stance! player-order 'high))
|
||||||
|
size: (vec 100 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 50
|
||||||
|
500)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"Mid Stance!")
|
||||||
|
(lambda ()
|
||||||
|
(set-order-stance! player-order 'mid))
|
||||||
|
size: (vec 100 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 50
|
||||||
|
540)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"Low Stance!")
|
||||||
|
(lambda ()
|
||||||
|
(set-order-stance! player-order 'low))
|
||||||
|
size: (vec 100 30)))
|
||||||
|
|
||||||
|
;; Attack inputs
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 12
|
||||||
|
320)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"Atk: Counter-clockwise")
|
||||||
|
(lambda ()
|
||||||
|
(set-order-atk! player-order (rotate-pos-cc (unit-hand-pos player-unit))))
|
||||||
|
size: (vec 175 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 12
|
||||||
|
360)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"Atk: From position!")
|
||||||
|
(lambda ()
|
||||||
|
(set-order-atk! player-order (unit-hand-pos player-unit)))
|
||||||
|
size: (vec 175 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 12
|
||||||
|
400)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"Atk: Clockwise!")
|
||||||
|
(lambda ()
|
||||||
|
(set-order-atk! player-order (rotate-pos (unit-hand-pos player-unit))))
|
||||||
|
size: (vec 175 30)))
|
||||||
|
|
||||||
|
;; Move inputs
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 185
|
||||||
|
517)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"<")
|
||||||
|
(lambda ()
|
||||||
|
(when (< 0 (v-y (unit-pos player-unit)))
|
||||||
|
(set-order-mov! player-order (vec 0 -1))))
|
||||||
|
size: (vec 30 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 255
|
||||||
|
517)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
">")
|
||||||
|
(lambda ()
|
||||||
|
(when (> 4 (v-y (unit-pos player-unit)))
|
||||||
|
(set-order-mov! player-order (vec 0 1))))
|
||||||
|
size: (vec 30 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 220
|
||||||
|
500)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"^")
|
||||||
|
(lambda ()
|
||||||
|
(when (< 0 (v-x (unit-pos player-unit)))
|
||||||
|
(set-order-mov! player-order (vec -1 0))))
|
||||||
|
size: (vec 30 30)))
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec 220
|
||||||
|
535)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"v")
|
||||||
|
(lambda ()
|
||||||
|
(when (> 4 (v-x (unit-pos player-unit)))
|
||||||
|
(set-order-mov! player-order (vec 1 0))))
|
||||||
|
size: (vec 30 30)))
|
||||||
|
|
||||||
|
;; End turn button
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec (- (/ (car (*window-size*))
|
||||||
|
2)
|
||||||
|
50)
|
||||||
|
500)
|
||||||
|
(footer (vec 0 0)
|
||||||
|
"Submit Order")
|
||||||
|
(lambda ()
|
||||||
|
(when (eqv? battle-state 'active)
|
||||||
|
(let ((o (enemy-order)))
|
||||||
|
(apply-order player-order player-unit)
|
||||||
|
(apply-order o enemy-unit)
|
||||||
|
(set! player-order (empty-order)))))))
|
||||||
|
|
||||||
|
;; Player data display
|
||||||
|
(entity
|
||||||
|
(footer
|
||||||
|
(vec 0 0)
|
||||||
|
""
|
||||||
|
centered: (cons #f #t))
|
||||||
|
(dynamic-label
|
||||||
|
(lambda ()
|
||||||
|
(conc (unit-health player-unit) "/3\n"
|
||||||
|
"Your hand is "
|
||||||
|
(direction-to-string (unit-hand-pos player-unit))
|
||||||
|
"\nStance: " (symbol->string (unit-stance player-unit))))))
|
||||||
|
|
||||||
|
;; Player order display
|
||||||
|
(entity
|
||||||
|
(footer
|
||||||
|
(vec 0 0)
|
||||||
|
"")
|
||||||
|
(dynamic-label
|
||||||
|
(lambda ()
|
||||||
|
(conc "Order:\n Move: "
|
||||||
|
(if (order-mov player-order)
|
||||||
|
(let ((m (order-mov player-order)))
|
||||||
|
(cond
|
||||||
|
((v= (vec 1 0) m) "Down")
|
||||||
|
((v= (vec -1 0) m) "Up")
|
||||||
|
((v= (vec 0 1) m) "Right")
|
||||||
|
((v= (vec 0 -1) m) "Left")))
|
||||||
|
"No change")
|
||||||
|
"\nAttack: " (if (order-atk player-order)
|
||||||
|
(direction-to-string (order-atk player-order))
|
||||||
|
"No change")
|
||||||
|
"\nStance: " (if (order-stance player-order)
|
||||||
|
(order-stance player-order)
|
||||||
|
"No change")))))
|
||||||
|
|
||||||
|
;; Enemy data display
|
||||||
|
(entity
|
||||||
|
(footer
|
||||||
|
(vec 600 0)
|
||||||
|
""
|
||||||
|
centered: (cons #f #t))
|
||||||
|
(dynamic-label
|
||||||
|
(lambda ()
|
||||||
|
(conc (unit-health enemy-unit) "/3\n"
|
||||||
|
"Their hand is "
|
||||||
|
(direction-to-string (unit-hand-pos enemy-unit))
|
||||||
|
"\nStance: " (symbol->string (unit-stance enemy-unit))))))
|
||||||
|
|
||||||
|
(entity
|
||||||
|
player-unit)
|
||||||
|
(entity
|
||||||
|
enemy-unit)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
@ -4,12 +4,14 @@
|
||||||
raylib
|
raylib
|
||||||
(imugi core)
|
(imugi core)
|
||||||
(imugi input)
|
(imugi input)
|
||||||
(main-menu))
|
(main-menu)
|
||||||
|
(arena))
|
||||||
|
|
||||||
(register-action 'click 'mouse-press MOUSE_BUTTON_LEFT)
|
(register-action 'click 'mouse-press MOUSE_BUTTON_LEFT)
|
||||||
|
|
||||||
((main-menu (lambda ()
|
((main-menu (lambda ()
|
||||||
(display "Loading game scene...")
|
(display "Loading game scene...")
|
||||||
(newline))))
|
(newline)
|
||||||
|
((arena)))))
|
||||||
|
|
||||||
(create-window))
|
(create-window))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue