Basic main menu and README
This commit is contained in:
parent
693879746b
commit
d450a0d155
8 changed files with 449 additions and 0 deletions
2
.dir-locals.el
Normal file
2
.dir-locals.el
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
((nil . ((geiser-default-implementation . chicken)
|
||||||
|
(geiser-active-implementations . (chicken)))))
|
||||||
75
README.org
Normal file
75
README.org
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#+title: Bitter Duel
|
||||||
|
|
||||||
|
This is a really simple tactics game for the [[https://itch.io/jam/spring-lisp-game-jam-2026][2026 Spring Lisp Game Jam]].
|
||||||
|
|
||||||
|
It is made in Chicken Scheme, using my own game framework [[https://git.cyan.sh/BirDt/imugi][Imugi]].
|
||||||
|
|
||||||
|
* Build
|
||||||
|
|
||||||
|
First install Chicken 5, then install Imugi using the instructions in its repo. You will also need to ~chicken-install csm~ for easier building.
|
||||||
|
|
||||||
|
Once both of those dependencies are installed, run:
|
||||||
|
#+begin_src shell
|
||||||
|
mkdir build && cd build
|
||||||
|
csm -program bitter-duel ..
|
||||||
|
./bitter-duel
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Design & Gameplay
|
||||||
|
|
||||||
|
In Bitter Duel, you control a single character on a 5 by 5 grid. There is a single opponent facing off against you.
|
||||||
|
|
||||||
|
Each character has a stance and hand position, and can move, attack, or assume a stance on their turn.
|
||||||
|
Each character has 3 health.
|
||||||
|
|
||||||
|
** Stances
|
||||||
|
Stances are initial striking positions, and provide some intrinsic bonus offense and defense on the turn that the stance is assumed.
|
||||||
|
|
||||||
|
After attacking or moving, your stance is broken until you next assume it.
|
||||||
|
|
||||||
|
There are 4 stances:
|
||||||
|
- High (Up-Left/Up-Right)
|
||||||
|
- 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
|
||||||
1
all.options
Normal file
1
all.options
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
-static -L /usr/local/lib/libraylib.a -L -lX11 -L -lXrandr -L -lXi -L -lXcursor -L -lXinerama -L -lXext -L -lGL -L -lm -L -lpthread -L -ldl -L -lrt
|
||||||
198
modules/ui.scm
Normal file
198
modules/ui.scm
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
(module (bd ui) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
(chicken module)
|
||||||
|
raylib
|
||||||
|
(imugi core)
|
||||||
|
(imugi math)
|
||||||
|
(imugi drawing)
|
||||||
|
(imugi resource)
|
||||||
|
(imugi input)
|
||||||
|
(srfi 1)
|
||||||
|
(srfi 4)
|
||||||
|
(srfi 99))
|
||||||
|
|
||||||
|
(define base-font (font "../res/fonts/Felipa-Regular.ttf"))
|
||||||
|
|
||||||
|
(define-record-type <label>
|
||||||
|
(int:make-label position centered? layer font font-size color text)
|
||||||
|
label?
|
||||||
|
(position label-pos set-label-pos!)
|
||||||
|
(centered? label-centered? set-label-centered!)
|
||||||
|
(layer label-layer set-label-layer!)
|
||||||
|
(font-size label-size set-label-size!)
|
||||||
|
(font label-font set-label-font!)
|
||||||
|
(color label-color set-label-color!)
|
||||||
|
(text label-text set-label-text!))
|
||||||
|
|
||||||
|
(export title)
|
||||||
|
(define (title position text
|
||||||
|
#!key
|
||||||
|
(centered (cons #f #f))
|
||||||
|
(layer 0)
|
||||||
|
(font base-font)
|
||||||
|
(size 128)
|
||||||
|
(color (make-color 0 0 0 1)))
|
||||||
|
(int:make-label position centered layer font size color text))
|
||||||
|
|
||||||
|
(export subtitle)
|
||||||
|
(define (subtitle position text
|
||||||
|
#!key
|
||||||
|
(centered (cons #f #f))
|
||||||
|
(layer 0)
|
||||||
|
(font base-font)
|
||||||
|
(size 36)
|
||||||
|
(color (make-color 0 0 0 1)))
|
||||||
|
(int:make-label position centered layer font size color text))
|
||||||
|
|
||||||
|
(export footer)
|
||||||
|
(define (footer position text
|
||||||
|
#!key
|
||||||
|
(centered (cons #f #f))
|
||||||
|
(layer 0)
|
||||||
|
(font base-font)
|
||||||
|
(size 24)
|
||||||
|
(color (make-color 0 0 0 1)))
|
||||||
|
(int:make-label position centered layer font size color text))
|
||||||
|
|
||||||
|
(export draw-labels)
|
||||||
|
(define draw-labels
|
||||||
|
(make-system
|
||||||
|
'draw-labels
|
||||||
|
10
|
||||||
|
'entity
|
||||||
|
'(<label>)
|
||||||
|
(lambda (_ label)
|
||||||
|
(push-render-object
|
||||||
|
'screen
|
||||||
|
(label-layer label)
|
||||||
|
(lambda ()
|
||||||
|
(let* (;; measure text length in pixels in case
|
||||||
|
;; we need it for horizontal centering
|
||||||
|
(text-length (f32vector->list
|
||||||
|
(measure-text-ex
|
||||||
|
(resource-contents (label-font label))
|
||||||
|
(label-text label)
|
||||||
|
(label-size label)
|
||||||
|
1)))
|
||||||
|
;; center the x/y of the position
|
||||||
|
;; based on label-centered?
|
||||||
|
(draw-pos (vec
|
||||||
|
(if (car (label-centered? label))
|
||||||
|
(- (/ (car (*window-size*))
|
||||||
|
2)
|
||||||
|
(/ (car text-length)
|
||||||
|
2))
|
||||||
|
(v-x (label-pos label)))
|
||||||
|
(if (cdr (label-centered? label))
|
||||||
|
(- (/ (cdr (*window-size*))
|
||||||
|
2)
|
||||||
|
(cadr text-length))
|
||||||
|
(v-y (label-pos label))))))
|
||||||
|
(draw-font-text-2d
|
||||||
|
draw-pos
|
||||||
|
(label-text label)
|
||||||
|
(label-size label)
|
||||||
|
(label-color label)
|
||||||
|
(label-font label))))))))
|
||||||
|
|
||||||
|
(define-record-type <button>
|
||||||
|
(int:make-button position size layer label state click-fn colors)
|
||||||
|
button?
|
||||||
|
(position button-pos set-button-pos!)
|
||||||
|
(size button-size set-button-size!)
|
||||||
|
(layer button-layer set-button-layer!)
|
||||||
|
(label button-label set-button-label!)
|
||||||
|
(state button-state set-button-state!)
|
||||||
|
(click-fn button-click-fn set-button-click-fn!)
|
||||||
|
(colors button-colors set-button-colors!))
|
||||||
|
|
||||||
|
(export button)
|
||||||
|
(define (button position label click-fn
|
||||||
|
#!key
|
||||||
|
(layer 0)
|
||||||
|
(size (vec 100 60))
|
||||||
|
(colors (list (make-color 0.48 0.48 0.48 1)
|
||||||
|
(make-color 0.63 0.63 0.63 1)
|
||||||
|
(make-color 0.39 0.39 0.39 1))))
|
||||||
|
(int:make-button position size layer label 'ready click-fn colors))
|
||||||
|
|
||||||
|
(define (check-button-state button)
|
||||||
|
(let ((x-range (cons (v-x (button-pos button))
|
||||||
|
(+ (v-x (button-pos button))
|
||||||
|
(v-x (button-size button)))))
|
||||||
|
(y-range (cons (v-y (button-pos button))
|
||||||
|
(+ (v-y (button-pos button))
|
||||||
|
(v-y (button-size button)))))
|
||||||
|
(mouse-pos (cons (get-mouse-x) (get-mouse-y))))
|
||||||
|
(if (and (< (car x-range) (car mouse-pos) (cdr x-range))
|
||||||
|
(< (car y-range) (cdr mouse-pos) (cdr y-range)))
|
||||||
|
(if (peek-event 'input 'click)
|
||||||
|
(set-button-state! button 'clicked)
|
||||||
|
(set-button-state! button 'hovered))
|
||||||
|
(set-button-state! button 'ready))))
|
||||||
|
|
||||||
|
(define (draw-button button)
|
||||||
|
(push-render-object
|
||||||
|
'screen
|
||||||
|
(button-layer button)
|
||||||
|
(lambda ()
|
||||||
|
(draw-rectangle-2d
|
||||||
|
(button-pos button)
|
||||||
|
(number->integer (v-x (button-size button)))
|
||||||
|
(number->integer (v-y (button-size button)))
|
||||||
|
(list-ref (button-colors button)
|
||||||
|
(case (button-state button)
|
||||||
|
((ready) 0)
|
||||||
|
((hovered) 1)
|
||||||
|
((clicked) 2)))
|
||||||
|
#t
|
||||||
|
1)))
|
||||||
|
(let* ((txt (button-label button))
|
||||||
|
(text-length (f32vector->list
|
||||||
|
(measure-text-ex
|
||||||
|
(resource-contents (label-font txt))
|
||||||
|
(label-text txt)
|
||||||
|
(label-size txt)
|
||||||
|
1)))
|
||||||
|
(center-offset (vec (- (/ (v-x (button-size button))
|
||||||
|
2)
|
||||||
|
(/ (car text-length)
|
||||||
|
2))
|
||||||
|
(- (/ (v-y (button-size button))
|
||||||
|
2)
|
||||||
|
(/ (cadr text-length)
|
||||||
|
2)))))
|
||||||
|
(push-render-object
|
||||||
|
'screen
|
||||||
|
(+ 1 (button-layer button))
|
||||||
|
(lambda ()
|
||||||
|
(draw-font-text-2d
|
||||||
|
(v+ (button-pos button)
|
||||||
|
center-offset)
|
||||||
|
(label-text txt)
|
||||||
|
(label-size txt)
|
||||||
|
(label-color txt)
|
||||||
|
(label-font txt))))))
|
||||||
|
|
||||||
|
(define (do-button-callback button)
|
||||||
|
(when (eqv? 'clicked (button-state button))
|
||||||
|
((button-click-fn button))))
|
||||||
|
|
||||||
|
(export handle-buttons)
|
||||||
|
(define handle-buttons
|
||||||
|
(make-system
|
||||||
|
'handle-buttons
|
||||||
|
10
|
||||||
|
'batch
|
||||||
|
'(<button>)
|
||||||
|
(lambda (buttons)
|
||||||
|
(for-each
|
||||||
|
(lambda (b)
|
||||||
|
(let ((button (find button? b)))
|
||||||
|
(check-button-state button)
|
||||||
|
(draw-button button)
|
||||||
|
(do-button-callback button)))
|
||||||
|
buttons)
|
||||||
|
(pop-event 'input 'click))))
|
||||||
|
)
|
||||||
BIN
res/fonts/Felipa-Regular.ttf
Normal file
BIN
res/fonts/Felipa-Regular.ttf
Normal file
Binary file not shown.
94
res/fonts/OFL.txt
Normal file
94
res/fonts/OFL.txt
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
Copyright (c) 2011 Fontstage (info@fontstage.com),
|
||||||
|
with Reserved Font Names, "Felipa"
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
https://openfontlicense.org
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
15
src/bitter-duel.scm
Normal file
15
src/bitter-duel.scm
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
(module (bitter-duel) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
raylib
|
||||||
|
(imugi core)
|
||||||
|
(imugi input)
|
||||||
|
(main-menu))
|
||||||
|
|
||||||
|
(register-action 'click 'mouse-press MOUSE_BUTTON_LEFT)
|
||||||
|
|
||||||
|
((main-menu (lambda ()
|
||||||
|
(display "Loading game scene...")
|
||||||
|
(newline))))
|
||||||
|
|
||||||
|
(create-window))
|
||||||
64
src/main-menu.scm
Normal file
64
src/main-menu.scm
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
(module (main-menu) ()
|
||||||
|
(import scheme
|
||||||
|
(chicken base)
|
||||||
|
(chicken module)
|
||||||
|
(imugi core)
|
||||||
|
(imugi input)
|
||||||
|
(imugi scene)
|
||||||
|
(imugi math)
|
||||||
|
(bd ui))
|
||||||
|
|
||||||
|
(export main-menu)
|
||||||
|
(define (main-menu play-callback)
|
||||||
|
(scene
|
||||||
|
push-actions
|
||||||
|
draw-labels
|
||||||
|
handle-buttons
|
||||||
|
|
||||||
|
;;; Text
|
||||||
|
;; Title
|
||||||
|
(entity
|
||||||
|
(title
|
||||||
|
(vec
|
||||||
|
;; 0 because automatically centered on x
|
||||||
|
0
|
||||||
|
(/ (cdr (*window-size*))
|
||||||
|
6))
|
||||||
|
"Bitter Duel"
|
||||||
|
centered: (cons #t #f)))
|
||||||
|
;; Subtitle
|
||||||
|
(entity
|
||||||
|
(subtitle
|
||||||
|
(vec
|
||||||
|
;; 0 because automatically centered on x
|
||||||
|
0
|
||||||
|
(/ (cdr (*window-size*))
|
||||||
|
3))
|
||||||
|
"Made for the Spring Lisp Game Jam 2026"
|
||||||
|
centered: (cons #t #f)))
|
||||||
|
;; Acknowledgements footer
|
||||||
|
(entity
|
||||||
|
(footer
|
||||||
|
(vec
|
||||||
|
;; 0 because automatically centered on x
|
||||||
|
0
|
||||||
|
(- (cdr (*window-size*))
|
||||||
|
30))
|
||||||
|
"By Jakub Nowak with Imugi+Raylib"
|
||||||
|
centered: (cons #t #f)))
|
||||||
|
|
||||||
|
(entity
|
||||||
|
(button
|
||||||
|
(vec (- (/ (car (*window-size*))
|
||||||
|
2)
|
||||||
|
50)
|
||||||
|
(- (/ (car (*window-size*))
|
||||||
|
2)
|
||||||
|
100))
|
||||||
|
(footer
|
||||||
|
(vec 0 0)
|
||||||
|
"Start Game!")
|
||||||
|
play-callback))
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue