Compare commits
24 Commits
023430315a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 57d8fa8cc5 | |||
| 777b70d1ab | |||
| 4ecaaf1b50 | |||
| 4ad280a820 | |||
| d3d1fa1430 | |||
| 7cfffde56d | |||
| 3f821d4258 | |||
| 9561db2847 | |||
| 719a9cd0f6 | |||
| 2dea06f8c7 | |||
| 479ff952cf | |||
| bed93d1de4 | |||
| 82d2a89a0a | |||
| 03b5d1dafb | |||
| 7f8d79e00f | |||
| fe8944b526 | |||
| c0d25f1d47 | |||
| 845c696899 | |||
| f71466d7fa | |||
| cfb04372de | |||
| 8662424c80 | |||
| 5aa71ac03f | |||
| 79bb1fdb0d | |||
| 9cec7f10db |
2
.gitignore
vendored
@@ -111,4 +111,4 @@ flycheck_*.el
|
|||||||
# Swap Files #
|
# Swap Files #
|
||||||
.*.kate-swp
|
.*.kate-swp
|
||||||
.swp.*
|
.swp.*
|
||||||
|
.kateproject*
|
||||||
|
|||||||
@@ -6,19 +6,23 @@ A dungeon crawler game made with LoveDOS for the DOSember Game Jam https://itch.
|
|||||||
|
|
||||||
### Sprites
|
### Sprites
|
||||||
- [B&W Ornamental Cursor by qubodup](https://opengameart.org/content/bw-ornamental-cursor-19x19)
|
- [B&W Ornamental Cursor by qubodup](https://opengameart.org/content/bw-ornamental-cursor-19x19)
|
||||||
- [Microchip texture by ZeptoBARS](https://opengameart.org/content/microchip-texture)
|
|
||||||
- [Eris in colour by Stephen](https://openclipart.org/detail/329762/eris-in-colour)
|
- [Eris in colour by Stephen](https://openclipart.org/detail/329762/eris-in-colour)
|
||||||
|
|
||||||
|
### Textures
|
||||||
|
- [Microchip texture by ZeptoBARS](https://opengameart.org/content/microchip-texture)
|
||||||
|
- [Assorted textures by Makkon](https://www.slipseer.com/index.php?resources/makkon-textures.28/)
|
||||||
|
|
||||||
### Sound effects
|
### Sound effects
|
||||||
- [Click.wav by frosty ham](https://opengameart.org/content/click-0)
|
- [Click.wav by frosty ham](https://opengameart.org/content/click-0)
|
||||||
- [Sci-Fi Sound Effects Library by Little Robot Sound Factory](https://opengameart.org/content/sci-fi-sound-effects-library)
|
- [Sci-Fi Sound Effects Library by Little Robot Sound Factory](https://opengameart.org/content/sci-fi-sound-effects-library)
|
||||||
|
|
||||||
### Music
|
### Music
|
||||||
|
|
||||||
- [Dogs of Cyberspace by congusbongus](https://modarchive.org/index.php?request=view_by_moduleid&query=207032)
|
- [Eskisky Zhi by Immorpher](https://immorpher.bandcamp.com/track/eskisky-zhi)
|
||||||
|
|
||||||
### Fonts
|
### Fonts
|
||||||
|
|
||||||
- [Concrete by Frank Baranowski](https://fontlibrary.org/en/font/concrete)
|
- [Concrete by Frank Baranowski](https://fontlibrary.org/en/font/concrete)
|
||||||
- [Nemoy by BSozoo](https://fontlibrary.org/en/font/nemoy)
|
- [Nemoy by BSozoo](https://fontlibrary.org/en/font/nemoy)
|
||||||
- [Banana Brick by artmaker](https://fontlibrary.org/en/font/banana-brick)
|
- [Banana Brick by artmaker](https://fontlibrary.org/en/font/banana-brick)
|
||||||
|
- [Block Buster letters (remix) by Arvin61r58 and The Big Red Computer Club](https://openclipart.org/detail/322048/block-buster-letters-remix)
|
||||||
|
|||||||
BIN
assets/bgm/eskisky.wav
Normal file
BIN
assets/imgs/concb03.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
BIN
assets/imgs/floppy.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 347 B |
BIN
assets/imgs/splash.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
assets/imgs/tchcmp1.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
BIN
assets/imgs/wally.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
bgm/dogs.wav
242
dosbox.conf
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
# This is the configurationfile for DOSBox 0.74. (Please use the latest version of DOSBox)
|
||||||
|
# Lines starting with a # are commentlines and are ignored by DOSBox.
|
||||||
|
# They are used to (briefly) document the effect of each option.
|
||||||
|
|
||||||
|
[sdl]
|
||||||
|
# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back)
|
||||||
|
# fulldouble: Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox.
|
||||||
|
# fullresolution: What resolution to use for fullscreen: original or fixed size (e.g. 1024x768).
|
||||||
|
# Using your monitor's native resolution with aspect=true might give the best results.
|
||||||
|
# If you end up with small window on a large screen, try an output different from surface.
|
||||||
|
# windowresolution: Scale the window to this size IF the output device supports hardware scaling.
|
||||||
|
# (output=surface does not!)
|
||||||
|
# output: What video system to use for output.
|
||||||
|
# Possible values: surface, overlay, opengl, openglnb, ddraw.
|
||||||
|
# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock)
|
||||||
|
# sensitivity: Mouse sensitivity.
|
||||||
|
# waitonerror: Wait before closing the console if dosbox has an error.
|
||||||
|
# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized.
|
||||||
|
# pause is only valid for the second entry.
|
||||||
|
# Possible values: lowest, lower, normal, higher, highest, pause.
|
||||||
|
# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the defaul value.
|
||||||
|
# usescancodes: Avoid usage of symkeys, might not work on all operating systems.
|
||||||
|
|
||||||
|
fullscreen=false
|
||||||
|
fulldouble=true
|
||||||
|
fullresolution=original
|
||||||
|
windowresolution=original
|
||||||
|
output=opengl
|
||||||
|
autolock=true
|
||||||
|
sensitivity=100
|
||||||
|
waitonerror=true
|
||||||
|
priority=higher,normal
|
||||||
|
mapperfile=mapper.map
|
||||||
|
usescancodes=true
|
||||||
|
|
||||||
|
[dosbox]
|
||||||
|
# language: Select another language file.
|
||||||
|
# machine: The type of machine tries to emulate.
|
||||||
|
# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe.
|
||||||
|
# captures: Directory where things like wave, midi, screenshot get captured.
|
||||||
|
# memsize: Amount of memory DOSBox has in megabytes.
|
||||||
|
# This value is best left at its default to avoid problems with some games,
|
||||||
|
# though few games might require a higher value.
|
||||||
|
# There is generally no speed advantage when raising this value.
|
||||||
|
|
||||||
|
language=
|
||||||
|
machine=svga_s3
|
||||||
|
captures=capture
|
||||||
|
memsize=128
|
||||||
|
|
||||||
|
[render]
|
||||||
|
# frameskip: How many frames DOSBox skips before drawing one.
|
||||||
|
# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!.
|
||||||
|
# scaler: Scaler used to enlarge/enhance low resolution modes.
|
||||||
|
# If 'forced' is appended, then the scaler will be used even if the result might not be desired.
|
||||||
|
# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
frameskip=0
|
||||||
|
aspect=true
|
||||||
|
scaler=normal2x
|
||||||
|
|
||||||
|
[cpu]
|
||||||
|
# core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate.
|
||||||
|
# Possible values: auto, dynamic, normal, simple.
|
||||||
|
# cputype: CPU Type used in emulation. auto is the fastest choice.
|
||||||
|
# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch.
|
||||||
|
# cycles: Amount of instructions DOSBox tries to emulate each millisecond.
|
||||||
|
# Setting this value too high results in sound dropouts and lags.
|
||||||
|
# Cycles can be set in 3 ways:
|
||||||
|
# 'auto' tries to guess what a game needs.
|
||||||
|
# It usually works, but can fail for certain games.
|
||||||
|
# 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails.
|
||||||
|
# (Example: fixed 4000).
|
||||||
|
# 'max' will allocate as much cycles as your computer is able to handle.
|
||||||
|
#
|
||||||
|
# Possible values: auto, fixed, max.
|
||||||
|
# cycleup: Amount of cycles to decrease/increase with keycombo.(CTRL-F11/CTRL-F12)
|
||||||
|
# cycledown: Setting it lower than 100 will be a percentage.
|
||||||
|
|
||||||
|
core=auto
|
||||||
|
cputype=auto
|
||||||
|
cycles=max
|
||||||
|
cycleup=1000
|
||||||
|
cycledown=1000
|
||||||
|
|
||||||
|
[mixer]
|
||||||
|
# nosound: Enable silent mode, sound is still emulated though.
|
||||||
|
# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality.
|
||||||
|
# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716.
|
||||||
|
# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged.
|
||||||
|
# Possible values: 1024, 2048, 4096, 8192, 512, 256.
|
||||||
|
# prebuffer: How many milliseconds of data to keep on top of the blocksize.
|
||||||
|
|
||||||
|
nosound=false
|
||||||
|
rate=44100
|
||||||
|
blocksize=1024
|
||||||
|
prebuffer=240
|
||||||
|
|
||||||
|
[midi]
|
||||||
|
# mpu401: Type of MPU-401 to emulate.
|
||||||
|
# Possible values: intelligent, uart, none.
|
||||||
|
# mididevice: Device that will receive the MIDI data from MPU-401.
|
||||||
|
# Possible values: default, win32, alsa, oss, coreaudio, coremidi, none.
|
||||||
|
# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use.
|
||||||
|
# See the README/Manual for more details.
|
||||||
|
|
||||||
|
mpu401=intelligent
|
||||||
|
mididevice=default
|
||||||
|
midiconfig=
|
||||||
|
|
||||||
|
[sblaster]
|
||||||
|
# sbtype: Type of Soundblaster to emulate. gb is Gameblaster.
|
||||||
|
# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none.
|
||||||
|
# sbbase: The IO address of the soundblaster.
|
||||||
|
# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300.
|
||||||
|
# irq: The IRQ number of the soundblaster.
|
||||||
|
# Possible values: 7, 5, 3, 9, 10, 11, 12.
|
||||||
|
# dma: The DMA number of the soundblaster.
|
||||||
|
# Possible values: 1, 5, 0, 3, 6, 7.
|
||||||
|
# hdma: The High DMA number of the soundblaster.
|
||||||
|
# Possible values: 1, 5, 0, 3, 6, 7.
|
||||||
|
# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer.
|
||||||
|
# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'.
|
||||||
|
# Possible values: auto, cms, opl2, dualopl2, opl3, none.
|
||||||
|
# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well).
|
||||||
|
# Possible values: default, compat, fast.
|
||||||
|
# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly).
|
||||||
|
# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000.
|
||||||
|
|
||||||
|
sbtype=sb16
|
||||||
|
sbbase=220
|
||||||
|
irq=7
|
||||||
|
dma=1
|
||||||
|
hdma=5
|
||||||
|
sbmixer=true
|
||||||
|
oplmode=opl2
|
||||||
|
oplemu=compat
|
||||||
|
oplrate=44100
|
||||||
|
|
||||||
|
[gus]
|
||||||
|
# gus: Enable the Gravis Ultrasound emulation.
|
||||||
|
# gusrate: Sample rate of Ultrasound emulation.
|
||||||
|
# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716.
|
||||||
|
# gusbase: The IO base address of the Gravis Ultrasound.
|
||||||
|
# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300.
|
||||||
|
# gusirq: The IRQ number of the Gravis Ultrasound.
|
||||||
|
# Possible values: 5, 3, 7, 9, 10, 11, 12.
|
||||||
|
# gusdma: The DMA channel of the Gravis Ultrasound.
|
||||||
|
# Possible values: 3, 0, 1, 5, 6, 7.
|
||||||
|
# ultradir: Path to Ultrasound directory. In this directory
|
||||||
|
# there should be a MIDI directory that contains
|
||||||
|
# the patch files for GUS playback. Patch sets used
|
||||||
|
# with Timidity should work fine.
|
||||||
|
|
||||||
|
gus=false
|
||||||
|
gusrate=44100
|
||||||
|
gusbase=240
|
||||||
|
gusirq=5
|
||||||
|
gusdma=3
|
||||||
|
ultradir=C:\ULTRASND
|
||||||
|
|
||||||
|
[speaker]
|
||||||
|
# pcspeaker: Enable PC-Speaker emulation.
|
||||||
|
# pcrate: Sample rate of the PC-Speaker sound generation.
|
||||||
|
# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716.
|
||||||
|
# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'.
|
||||||
|
# Possible values: auto, on, off.
|
||||||
|
# tandyrate: Sample rate of the Tandy 3-Voice generation.
|
||||||
|
# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716.
|
||||||
|
# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible).
|
||||||
|
|
||||||
|
pcspeaker=true
|
||||||
|
pcrate=44100
|
||||||
|
tandy=auto
|
||||||
|
tandyrate=44100
|
||||||
|
disney=true
|
||||||
|
|
||||||
|
[joystick]
|
||||||
|
# joysticktype: Type of joystick to emulate: auto (default), none,
|
||||||
|
# 2axis (supports two joysticks),
|
||||||
|
# 4axis (supports one joystick, first joystick used),
|
||||||
|
# 4axis_2 (supports one joystick, second joystick used),
|
||||||
|
# fcs (Thrustmaster), ch (CH Flightstick).
|
||||||
|
# none disables joystick emulation.
|
||||||
|
# auto chooses emulation depending on real joystick(s).
|
||||||
|
# (Remember to reset dosbox's mapperfile if you saved it earlier)
|
||||||
|
# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none.
|
||||||
|
# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away).
|
||||||
|
# autofire: continuously fires as long as you keep the button pressed.
|
||||||
|
# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks.
|
||||||
|
# buttonwrap: enable button wrapping at the number of emulated buttons.
|
||||||
|
|
||||||
|
joysticktype=auto
|
||||||
|
timed=true
|
||||||
|
autofire=false
|
||||||
|
swap34=false
|
||||||
|
buttonwrap=false
|
||||||
|
|
||||||
|
[serial]
|
||||||
|
# serial1: set type of device connected to com port.
|
||||||
|
# Can be disabled, dummy, modem, nullmodem, directserial.
|
||||||
|
# Additional parameters must be in the same line in the form of
|
||||||
|
# parameter:value. Parameter for all types is irq (optional).
|
||||||
|
# for directserial: realport (required), rxdelay (optional).
|
||||||
|
# (realport:COM1 realport:ttyS0).
|
||||||
|
# for modem: listenport (optional).
|
||||||
|
# for nullmodem: server, rxdelay, txdelay, telnet, usedtr,
|
||||||
|
# transparent, port, inhsocket (all optional).
|
||||||
|
# Example: serial1=modem listenport:5000
|
||||||
|
# Possible values: dummy, disabled, modem, nullmodem, directserial.
|
||||||
|
# serial2: see serial1
|
||||||
|
# Possible values: dummy, disabled, modem, nullmodem, directserial.
|
||||||
|
# serial3: see serial1
|
||||||
|
# Possible values: dummy, disabled, modem, nullmodem, directserial.
|
||||||
|
# serial4: see serial1
|
||||||
|
# Possible values: dummy, disabled, modem, nullmodem, directserial.
|
||||||
|
|
||||||
|
serial1=dummy
|
||||||
|
serial2=dummy
|
||||||
|
serial3=disabled
|
||||||
|
serial4=disabled
|
||||||
|
|
||||||
|
[dos]
|
||||||
|
# xms: Enable XMS support.
|
||||||
|
# ems: Enable EMS support.
|
||||||
|
# umb: Enable UMB support.
|
||||||
|
# keyboardlayout: Language code of the keyboard layout (or none).
|
||||||
|
|
||||||
|
xms=true
|
||||||
|
ems=true
|
||||||
|
umb=true
|
||||||
|
keyboardlayout=auto
|
||||||
|
|
||||||
|
[ipx]
|
||||||
|
# ipx: Enable ipx over UDP/IP emulation.
|
||||||
|
|
||||||
|
Enable=0
|
||||||
|
Connection=0
|
||||||
|
ipx=false
|
||||||
BIN
imgs/splash.png
|
Before Width: | Height: | Size: 12 KiB |
BIN
imgs/wally.png
|
Before Width: | Height: | Size: 24 KiB |
97
licenses/OFL.TXT
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
Copyright (c) <dates>, <Copyright Holder> (<URL|email>),
|
||||||
|
with Reserved Font Name <Reserved Font Name>.
|
||||||
|
Copyright (c) <dates>, <additional Copyright Holder> (<URL|email>),
|
||||||
|
with Reserved Font Name <additional Reserved Font Name>.
|
||||||
|
Copyright (c) <dates>, <additional Copyright Holder> (<URL|email>).
|
||||||
|
|
||||||
|
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.
|
||||||
31
main.lua
@@ -2,9 +2,10 @@
|
|||||||
-- Imports
|
-- Imports
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local love = require 'love'
|
local love = require 'love'
|
||||||
local game_states = require 'src.states'
|
local game_states = require 'src.states'
|
||||||
local Fader = require 'src.utils.fader'
|
local settings = require 'src.utils.settings'
|
||||||
|
local Fader = require 'src.graphics.fader'
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@@ -12,9 +13,9 @@ local Fader = require 'src.utils.fader'
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
Current_state = 1
|
Current_state = 1
|
||||||
Fade = Fader()
|
Fade = Fader()
|
||||||
Change_state = false
|
Change_state = false
|
||||||
Debug = false
|
Debug = false
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@@ -23,8 +24,8 @@ Debug = false
|
|||||||
|
|
||||||
local function parse_args(args)
|
local function parse_args(args)
|
||||||
for _, v in pairs(args) do
|
for _, v in pairs(args) do
|
||||||
-- Enable debug mode.
|
if v == '-debug' then Debug = true end
|
||||||
if v == '-debug' then Debug = true end
|
if v == '-skip-intro' then Current_state = 2 end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -36,6 +37,9 @@ end
|
|||||||
function love.load(args)
|
function love.load(args)
|
||||||
parse_args(args)
|
parse_args(args)
|
||||||
|
|
||||||
|
-- Obtain the settings for the game.
|
||||||
|
settings:load_settings()
|
||||||
|
|
||||||
-- Load the assets of the intro game state.
|
-- Load the assets of the intro game state.
|
||||||
game_states[Current_state]:load()
|
game_states[Current_state]:load()
|
||||||
|
|
||||||
@@ -61,13 +65,15 @@ function love.update(dt)
|
|||||||
if Fade.done then
|
if Fade.done then
|
||||||
game_states[Current_state]:unload(dt)
|
game_states[Current_state]:unload(dt)
|
||||||
love.event.quit()
|
love.event.quit()
|
||||||
|
|
||||||
|
-- Save the settings before quitting just in case.
|
||||||
|
settings:save_settings()
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- If the new state exists then unload it's data and set the new state.
|
-- If the new state exists then unload it's data and set the new state.
|
||||||
if Change_state and Fade.done then
|
if Change_state and Fade.done then
|
||||||
game_states[Current_state]:unload(dt)
|
game_states[Current_state]:unload(dt)
|
||||||
Current_state = new_state
|
Current_state = new_state
|
||||||
game_states[Current_state]:load()
|
|
||||||
Change_state = false
|
Change_state = false
|
||||||
Fade:fade_in()
|
Fade:fade_in()
|
||||||
end
|
end
|
||||||
@@ -81,9 +87,14 @@ function love.draw()
|
|||||||
Fade:draw()
|
Fade:draw()
|
||||||
|
|
||||||
if Debug then
|
if Debug then
|
||||||
|
-- love.graphics.setColor(0, 0, 0)
|
||||||
|
-- love.graphics.rectangle('fill', 0, 0, 140, 50)
|
||||||
|
love.graphics.setColor(255, 250, 0)
|
||||||
love.graphics.print(string.format('OS: %s', love.system.getOS()), 5, 5)
|
love.graphics.print(string.format('OS: %s', love.system.getOS()), 5, 5)
|
||||||
love.graphics.print(string.format('Love version: %s', love.getVersion()), 5, 15)
|
love.graphics.print(string.format('Love version: %s', love.getVersion()), 5, 15)
|
||||||
love.graphics.print(string.format('Memory usage: %s KiB', love.system.getMemUsage()), 5, 25)
|
love.graphics.print(string.format('Memory usage: %s KiB', love.system.getMemUsage()), 5, 25)
|
||||||
|
love.graphics.print(string.format('FPS: %.2f', 1.0 / love.timer.getAverageDelta()), 5, 35)
|
||||||
|
love.graphics.setColor()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -123,7 +134,7 @@ end
|
|||||||
function love.mousepressed(x, y, btn)
|
function love.mousepressed(x, y, btn)
|
||||||
-- Send events to the active game state if there is no fade active.
|
-- Send events to the active game state if there is no fade active.
|
||||||
if Fade.done then
|
if Fade.done then
|
||||||
game_states[Current_state]:mousemoved(x, y, btn)
|
game_states[Current_state]:mousepressed(x, y, btn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
58
src/graphics/drawable.lua
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Drawable
|
||||||
|
local Drawable = make_class()
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Drawable:_init()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:update(_)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:keypressed(_, _ , _)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:textinput(_)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:keyreleased(_, _)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:mousemoved(_, _, _, _)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:mousepressed(_, _, _)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Drawable:mousereleased(_, _, _)
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Drawable
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
-- Imports
|
-- Imports
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local love = require 'love'
|
local love = require 'love'
|
||||||
local make_class = require 'src.utils.classes'
|
local make_class = require 'src.utils.classes'
|
||||||
|
|
||||||
|
|
||||||
@@ -18,16 +18,16 @@ local Fader = make_class()
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
function Fader:_init()
|
function Fader:_init()
|
||||||
self.t = 0.0
|
self.t = 0.0
|
||||||
self.step = 0
|
self.step = 0
|
||||||
self.done = true
|
self.done = true
|
||||||
self.reverse = false
|
self.reverse = false
|
||||||
self.callback = nil
|
self.callback = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Fader:_reset()
|
function Fader:_reset()
|
||||||
self.t = 0
|
self.t = 0
|
||||||
self.step = 0
|
self.step = 0
|
||||||
self.done = false
|
self.done = false
|
||||||
end
|
end
|
||||||
@@ -35,29 +35,35 @@ end
|
|||||||
|
|
||||||
function Fader:fade_in(callback)
|
function Fader:fade_in(callback)
|
||||||
self:_reset()
|
self:_reset()
|
||||||
self.reverse = true
|
self.reverse = true
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Fader:fade_out(callback)
|
function Fader:fade_out(callback)
|
||||||
self:_reset()
|
self:_reset()
|
||||||
self.reverse = false
|
self.reverse = false
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Fader:update(dt)
|
function Fader:update(dt)
|
||||||
|
-- While the fader is active.
|
||||||
if not self.done then
|
if not self.done then
|
||||||
|
-- Update the internal timer.
|
||||||
self.t = self.t + dt
|
self.t = self.t + dt
|
||||||
|
|
||||||
|
-- Advance the fade if enough time has passed.
|
||||||
if self.t >= 0.009 then
|
if self.t >= 0.009 then
|
||||||
self.step = self.step + 1
|
self.step = self.step + 1
|
||||||
self.t = 0.0
|
self.t = 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Mark as done when all fade tiles have been shown/hidden.
|
||||||
if self.step > 175 then
|
if self.step > 175 then
|
||||||
self.done = true
|
self.done = true
|
||||||
|
|
||||||
|
-- Execute the callback if any.
|
||||||
if self.callback ~= nil then
|
if self.callback ~= nil then
|
||||||
self.callback()
|
self.callback()
|
||||||
self.callback = nil
|
self.callback = nil
|
||||||
@@ -68,24 +74,33 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function Fader:draw()
|
function Fader:draw()
|
||||||
local c = 0
|
local c = 1
|
||||||
|
|
||||||
|
-- Set the render color to black.
|
||||||
love.graphics.setColor(0, 0, 0)
|
love.graphics.setColor(0, 0, 0)
|
||||||
|
|
||||||
|
-- For every fader tile.
|
||||||
for i = 0, 16 do
|
for i = 0, 16 do
|
||||||
for j = 0, 10 do
|
for j = 0, 10 do
|
||||||
|
-- Check if this is a fade in or fade out.
|
||||||
if not self.reverse then
|
if not self.reverse then
|
||||||
|
-- If it's a fade out then draw black tiles until c.
|
||||||
if c <= self.step then
|
if c <= self.step then
|
||||||
love.graphics.rectangle('fill', 20 * i, 20 * j, 20, 20)
|
love.graphics.rectangle('fill', 20 * i, 20 * j, 20, 20)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if c <= self.step then else
|
-- If it's a fade in then draw black tiles with indices higher than c.
|
||||||
|
if c > self.step then
|
||||||
love.graphics.rectangle('fill', 20 * i, 20 * j, 20, 20)
|
love.graphics.rectangle('fill', 20 * i, 20 * j, 20, 20)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Advance to the next tile to show/hide.
|
||||||
c = c + 1
|
c = c + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Reset the render color to white.
|
||||||
love.graphics.setColor()
|
love.graphics.setColor()
|
||||||
end
|
end
|
||||||
|
|
||||||
56
src/graphics/sprite.lua
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Asset = require 'src.utils.asset'
|
||||||
|
local Drawable = require 'src.graphics.drawable'
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Sprite = make_class(Drawable, Asset)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Sprite:_init(file_name, x, y)
|
||||||
|
Asset._init(self, file_name)
|
||||||
|
self.x = (x ~= nil and x) or 0
|
||||||
|
self.y = (y ~= nil and y) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Sprite:load()
|
||||||
|
if not self:is_loaded() then
|
||||||
|
self.sprite = love.graphics.newImage(self.file_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Sprite:unload()
|
||||||
|
self.sprite = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Sprite:is_loaded()
|
||||||
|
return self.sprite ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Sprite:draw()
|
||||||
|
if self.sprite ~= nil then
|
||||||
|
love.graphics.draw(self.sprite, self.x, self.y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Sprite
|
||||||
@@ -3,13 +3,15 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local make_class = require 'src.utils.classes'
|
local make_class = require 'src.utils.classes'
|
||||||
|
local assets = require 'src.utils.asstmngr'
|
||||||
|
local Drawable = require 'src.graphics.drawable'
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- Class definitions
|
-- Class definitions
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local GameState = make_class()
|
local GameState = make_class(Drawable)
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@@ -17,9 +19,15 @@ local GameState = make_class()
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
function GameState:_init(name, index)
|
function GameState:_init(name, index)
|
||||||
self.name = name
|
Drawable._init(self)
|
||||||
self.index = index
|
self.name = name
|
||||||
self.valid = false
|
self.index = index
|
||||||
|
self.next_state = self.index
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function GameState:update(_)
|
||||||
|
return self.next_state
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -27,42 +35,11 @@ function GameState:load()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GameState:update(_)
|
|
||||||
return self.index
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:draw()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:unload()
|
function GameState:unload()
|
||||||
|
assets:unload(self.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GameState:keypressed(_, _ , _)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:textinput(_)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:keyreleased(_, _)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:mousemoved(_, _, _, _)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:mousepressed(_, _, _)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function GameState:mousereleased(_, _, _)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- Module return
|
-- Module return
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
-- Imports
|
-- Imports
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local love = require 'love'
|
local make_class = require 'src.utils.classes'
|
||||||
local make_class = require 'src.utils.classes'
|
local GameState = require 'src.gstates.gstate'
|
||||||
local GameState = require 'src.gstates.gstate'
|
local Sprite = require 'src.graphics.sprite'
|
||||||
local Fader = require 'src.utils.fader'
|
local Fader = require 'src.graphics.fader'
|
||||||
|
local SoundEffect = require 'src.sound.sfx'
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- Class definitions
|
-- Class definitions
|
||||||
@@ -21,22 +21,31 @@ local Intro = make_class(GameState)
|
|||||||
|
|
||||||
function Intro:_init(name, index)
|
function Intro:_init(name, index)
|
||||||
GameState._init(self, name, index)
|
GameState._init(self, name, index)
|
||||||
self.skip = false
|
self.skip = false
|
||||||
self.fade = Fader()
|
self.fade = Fader()
|
||||||
self.stage = 0
|
self.stage = 0
|
||||||
self.timer = 0
|
self.timer = 0
|
||||||
|
|
||||||
|
self.splash = Sprite('imgs/splash.png')
|
||||||
|
self.author = Sprite('imgs/wally.png')
|
||||||
|
self.title = Sprite('imgs/title.png')
|
||||||
|
|
||||||
|
self.splash_snd = SoundEffect('snd/jachiev.wav')
|
||||||
|
self.author_snd = SoundEffect('snd/alang.wav')
|
||||||
|
self.title_snd = SoundEffect('snd/ablhole.wav')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Intro:load()
|
function Intro:load()
|
||||||
self.splash = love.graphics.newImage('imgs/splash.png')
|
-- Load all assets.
|
||||||
self.author = love.graphics.newImage('imgs/wally.png')
|
self.splash:load()
|
||||||
self.title = love.graphics.newImage('imgs/title.png')
|
self.author:load()
|
||||||
self.splash_snd = love.audio.newSource('snd/jachiev.wav')
|
self.title:load()
|
||||||
self.author_snd = love.audio.newSource('snd/alang.wav')
|
self.splash_snd:load()
|
||||||
self.title_snd = love.audio.newSource('snd/ablhole.wav')
|
self.author_snd:load()
|
||||||
self.valid = true
|
self.title_snd:load()
|
||||||
|
|
||||||
|
-- Play the initial sound effect.
|
||||||
self.splash_snd:play()
|
self.splash_snd:play()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -44,21 +53,25 @@ end
|
|||||||
function Intro:update(dt)
|
function Intro:update(dt)
|
||||||
local total_time
|
local total_time
|
||||||
|
|
||||||
|
-- Set time to wait for each intro stage.
|
||||||
if self.stage == 0 then
|
if self.stage == 0 then
|
||||||
total_time = 4.5
|
total_time = 6.5
|
||||||
elseif self.stage == 1 then
|
elseif self.stage == 1 then
|
||||||
total_time = 3.0
|
total_time = 5.0
|
||||||
else
|
else
|
||||||
total_time = 8.0
|
total_time = 8.0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Start counting the stage time when the fade in is done.
|
||||||
if self.fade.done then
|
if self.fade.done then
|
||||||
self.timer = self.timer + dt
|
self.timer = self.timer + dt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check if it's time to change stage.
|
||||||
if self.timer >= total_time then
|
if self.timer >= total_time then
|
||||||
self.fade:fade_out(
|
self.fade:fade_out(
|
||||||
function ()
|
function ()
|
||||||
|
-- Change the stage and play the corresponding sound.
|
||||||
self.stage = self.stage + 1
|
self.stage = self.stage + 1
|
||||||
|
|
||||||
if self.stage == 1 then
|
if self.stage == 1 then
|
||||||
@@ -67,41 +80,47 @@ function Intro:update(dt)
|
|||||||
self.title_snd:play()
|
self.title_snd:play()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Request a fade in.
|
||||||
self.fade:fade_in()
|
self.fade:fade_in()
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
-- Reset the stage timer.
|
||||||
self.timer = 0.0
|
self.timer = 0.0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Update the fader.
|
||||||
self.fade:update(dt)
|
self.fade:update(dt)
|
||||||
|
|
||||||
|
-- Move on to the next game state if the user skipped the intro or all stages are complete.
|
||||||
if not self.skip and self.stage < 3 then return self.index else return 2 end
|
if not self.skip and self.stage < 3 then return self.index else return 2 end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Intro:draw()
|
function Intro:draw()
|
||||||
if self.valid then
|
-- If there is data to draw, then draw the current stage's backdrop.
|
||||||
if self.stage == 0 then love.graphics.draw(self.splash, 0, 0)
|
if self.stage == 0 then self.splash:draw()
|
||||||
elseif self.stage == 1 then love.graphics.draw(self.author, 0, 0)
|
elseif self.stage == 1 then self.author:draw()
|
||||||
elseif self.stage == 2 then love.graphics.draw(self.title, 0, 0) end
|
elseif self.stage == 2 then self.title:draw() end
|
||||||
end
|
|
||||||
|
|
||||||
|
-- Draw the fader if needed.
|
||||||
self.fade:draw()
|
self.fade:draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Intro:unload()
|
function Intro:unload()
|
||||||
self.splash = nil
|
-- Null all assets so they can be claimed by the GC.
|
||||||
self.author = nil
|
self.splash:unload()
|
||||||
self.title = nil
|
self.author:unload()
|
||||||
self.splash_snd = nil
|
self.title:unload()
|
||||||
self.author_snd = nil
|
self.splash_snd:unload()
|
||||||
self.title_snd = nil
|
self.author_snd:unload()
|
||||||
self.valid = false
|
self.title_snd:unload()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function Intro:keypressed(_)
|
function Intro:keypressed(_)
|
||||||
|
-- Skip the intro on any key press.
|
||||||
self.skip = true
|
self.skip = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
185
src/gstates/menu.lua
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local assets = require 'src.utils.asstmngr'
|
||||||
|
local sound_manager = require 'src.sound.sndmngr'
|
||||||
|
local dialog_manager = require 'src.ui.dlgmngr'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local constants = require 'src.gstates.menus.const'
|
||||||
|
local GameState = require 'src.gstates.gstate'
|
||||||
|
local MainMenu = require 'src.gstates.menus.mainmenu'
|
||||||
|
local OptionsMenu = require 'src.gstates.menus.options'
|
||||||
|
local Fader = require 'src.graphics.fader'
|
||||||
|
local Cursor = require 'src.ui.cursor'
|
||||||
|
local Font = require 'src.ui.font'
|
||||||
|
local SoundEffect = require 'src.sound.sfx'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Menu = make_class(GameState)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Menu:_init(name, index)
|
||||||
|
GameState._init(self, name, index)
|
||||||
|
self.fade = Fader()
|
||||||
|
self.current_menu = constants.MAIN_MENU
|
||||||
|
self.next_menu = constants.MAIN_MENU
|
||||||
|
self.all_loaded = false
|
||||||
|
|
||||||
|
-- Create sprites and buttons.
|
||||||
|
self.btn_font = Font('fonts/Concrete.ttf')
|
||||||
|
self.title_font = Font('fonts/BBrick.ttf', 35)
|
||||||
|
|
||||||
|
-- Create a mouse cursor object at the current mouse position.
|
||||||
|
local mx, my = love.mouse.getPosition()
|
||||||
|
self.cursor = Cursor(mx, my)
|
||||||
|
|
||||||
|
-- Create sound effects.
|
||||||
|
self.bgm = SoundEffect('bgm/eskisky.wav')
|
||||||
|
|
||||||
|
-- Create the sub-menus.
|
||||||
|
self.menus = { }
|
||||||
|
self.menus[constants.MAIN_MENU] = MainMenu(self, self.title_font, self.btn_font)
|
||||||
|
self.menus[constants.OPTIONS_MENU] = OptionsMenu(self, self.title_font, self.btn_font)
|
||||||
|
|
||||||
|
-- Register all assets.
|
||||||
|
assets:register(self.name, self.btn_font)
|
||||||
|
assets:register(self.name, self.title_font)
|
||||||
|
assets:register(self.name, self.cursor)
|
||||||
|
assets:register(self.name, self.bgm)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Menu:update(dt)
|
||||||
|
if not self.bgm:isPlaying() then sound_manager:play_music(self.bgm) end
|
||||||
|
|
||||||
|
if self.all_loaded then
|
||||||
|
self.menus[self.current_menu]:update(dt)
|
||||||
|
dialog_manager:update(dt)
|
||||||
|
|
||||||
|
-- If the game state changed then trigger a fade out.
|
||||||
|
if self.next_menu ~= self.current_menu and self.fade.done then
|
||||||
|
self.fade:fade_out()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.fade:update(dt)
|
||||||
|
|
||||||
|
-- Update the game state.
|
||||||
|
if self.menus[self.next_menu] == nil then
|
||||||
|
error(string.format('%s: switched to unknown menu', self.next_menu))
|
||||||
|
else
|
||||||
|
-- If the new state exists then unload it's data and set the new state.
|
||||||
|
if self.next_menu ~= self.current_menu and self.fade.done then
|
||||||
|
self.current_menu = self.next_menu
|
||||||
|
self.fade:fade_in()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local done = true
|
||||||
|
|
||||||
|
assets:update(self.name)
|
||||||
|
|
||||||
|
for _, v in pairs(self.menus) do
|
||||||
|
assets:update(v.name)
|
||||||
|
done = done and assets:done(v.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.all_loaded = assets:done(self.name) and done
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.next_state
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Menu:draw()
|
||||||
|
if self.all_loaded then
|
||||||
|
self.menus[self.current_menu]:draw()
|
||||||
|
dialog_manager:draw()
|
||||||
|
self.cursor:draw()
|
||||||
|
self.fade:draw()
|
||||||
|
else
|
||||||
|
assets:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Menu:keypressed(key, code, isrepeat)
|
||||||
|
-- Send events to the active game state if there is no fade active.
|
||||||
|
if Fade.done then
|
||||||
|
if dialog_manager:empty() then
|
||||||
|
self.menus[self.current_menu]:keypressed(key, code, isrepeat)
|
||||||
|
else
|
||||||
|
dialog_manager:keypressed(key, code, isrepeat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Menu:keyreleased(key, code)
|
||||||
|
-- Send events to the active game state if there is no fade active.
|
||||||
|
if Fade.done then
|
||||||
|
if dialog_manager:empty() then
|
||||||
|
self.menus[self.current_menu]:keyreleased(key, code)
|
||||||
|
else
|
||||||
|
dialog_manager:keyreleased(key, code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Menu:textinput(text)
|
||||||
|
-- Send events to the active game state if there is no fade active.
|
||||||
|
if Fade.done then
|
||||||
|
if dialog_manager:empty() then
|
||||||
|
self.menus[self.current_menu]:textinput(text)
|
||||||
|
else
|
||||||
|
dialog_manager:textinput(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Menu:mousemoved(x, y, dx, dy)
|
||||||
|
if dialog_manager:empty() then
|
||||||
|
self.menus[self.current_menu]:mousemoved(x, y, dx, dy)
|
||||||
|
else
|
||||||
|
dialog_manager:mousemoved(x, y, dx, dy)
|
||||||
|
end
|
||||||
|
self.cursor:mousemoved(x, y, dx, dy)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Menu:mousepressed(x, y, btn)
|
||||||
|
if self.fade.done then
|
||||||
|
if dialog_manager:empty() then
|
||||||
|
self.menus[self.current_menu]:mousepressed(x, y, btn)
|
||||||
|
else
|
||||||
|
dialog_manager:mousepressed(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Menu:mousereleased(x, y, btn)
|
||||||
|
if self.fade.done then
|
||||||
|
if dialog_manager:empty() then
|
||||||
|
self.menus[self.current_menu]:mousereleased(x, y, btn)
|
||||||
|
else
|
||||||
|
dialog_manager:mousereleased(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Menu
|
||||||
75
src/gstates/menus/base.lua
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local assets = require 'src.utils.asstmngr'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local GameState = require 'src.gstates.gstate'
|
||||||
|
local Sprite = require 'src.graphics.sprite'
|
||||||
|
local VBox = require 'src.ui.vbox'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local BaseMenu = make_class(GameState)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function BaseMenu:_init(parent, name, index, bckg)
|
||||||
|
GameState._init(self, name, index)
|
||||||
|
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
-- Create background sprite and container.
|
||||||
|
self.background = Sprite(bckg)
|
||||||
|
self.container = VBox(15, 5, love.graphics.getWidth() - 15)
|
||||||
|
|
||||||
|
-- Register the background and container into the asset manager.
|
||||||
|
assets:register(self.name, self.background)
|
||||||
|
assets:register(self.name, self.container)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BaseMenu:mousemoved(x, y, dx, dy)
|
||||||
|
self.container:mousemoved(x, y, dx, dy)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BaseMenu:mousepressed(x, y, btn)
|
||||||
|
self.container:mousepressed(x, y, btn)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BaseMenu:mousereleased(x, y, btn)
|
||||||
|
self.container:mousereleased(x, y, btn)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BaseMenu:update()
|
||||||
|
if not assets:done(self.name) then
|
||||||
|
assets:update(self.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function BaseMenu:draw()
|
||||||
|
if assets:done(self.name) then
|
||||||
|
self.background:draw()
|
||||||
|
self.container:draw()
|
||||||
|
else
|
||||||
|
assets:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return BaseMenu
|
||||||
17
src/gstates/menus/const.lua
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Constants
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local constants = {
|
||||||
|
MAIN_MENU = 1,
|
||||||
|
OPTIONS_MENU = 2,
|
||||||
|
STORY = 3,
|
||||||
|
LOAD_MENU = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return constants
|
||||||
41
src/gstates/menus/mainmenu.lua
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local constants = require 'src.gstates.menus.const'
|
||||||
|
local BaseMenu = require 'src.gstates.menus.base'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
local Label = require 'src.ui.label'
|
||||||
|
local TextButton = require 'src.ui.textbtn'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local MainMenu = make_class(BaseMenu)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Main Menu Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function MainMenu:_init(parent, title_font, button_font)
|
||||||
|
BaseMenu._init(self, parent, "Main Menu", constants.MAIN_MENU, 'imgs/concb03.png')
|
||||||
|
|
||||||
|
-- Create UI elements of the main menu.
|
||||||
|
self.container:add(Label(nil, nil, 'LoveDOS', title_font, Color(215, 0, 0), true))
|
||||||
|
self.container:add(TextButton('New Game', button_font))
|
||||||
|
self.container:add(TextButton('Load Game', button_font))
|
||||||
|
self.container:add(TextButton('Options', button_font, nil, nil, function() parent.next_menu = constants.OPTIONS_MENU end))
|
||||||
|
self.container:add(TextButton('Help & Story', button_font))
|
||||||
|
self.container:add(TextButton('Quit', button_font, nil, nil, function() parent.next_state = -1 end))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return MainMenu
|
||||||
178
src/gstates/menus/options.lua
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local constants = require 'src.gstates.menus.const'
|
||||||
|
local settings = require 'src.utils.settings'
|
||||||
|
local sound_manager = require 'src.sound.sndmngr'
|
||||||
|
local assets = require 'src.utils.asstmngr'
|
||||||
|
local BaseMenu = require 'src.gstates.menus.base'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
local HBox = require 'src.ui.hbox'
|
||||||
|
local Label = require 'src.ui.label'
|
||||||
|
local TextButton = require 'src.ui.textbtn'
|
||||||
|
local TextInput = require 'src.ui.textinpt'
|
||||||
|
local Checkbox = require 'src.ui.chkbox'
|
||||||
|
local Bar = require 'src.ui.bar'
|
||||||
|
local Dialog = require 'src.ui.dialog'
|
||||||
|
local Font = require 'src.ui.font'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local OptionsMenu = make_class(BaseMenu)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function OptionsMenu:_init(parent, title_font, button_font)
|
||||||
|
BaseMenu._init(self, parent, "Options Menu", constants.OPTIONS_MENU, 'imgs/cpu.png')
|
||||||
|
|
||||||
|
self.subtitle_font = Font('fonts/BBrick.ttf', 25)
|
||||||
|
|
||||||
|
-- Create UI elements of the menu.
|
||||||
|
self.container:add(Label(nil, nil, 'Options', title_font, Color(215, 0, 0), true))
|
||||||
|
|
||||||
|
-- Permadeath checkbox.
|
||||||
|
local box = HBox()
|
||||||
|
|
||||||
|
box:add(Label(nil, nil, 'Enable Permadeath: ', button_font))
|
||||||
|
box:add(Checkbox(
|
||||||
|
function()
|
||||||
|
settings.permadeath = not settings.permadeath
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
return settings.permadeath
|
||||||
|
end,
|
||||||
|
17,
|
||||||
|
15))
|
||||||
|
|
||||||
|
self.container:add(box)
|
||||||
|
|
||||||
|
-- Control binding dialog.
|
||||||
|
local dlg = Dialog('imgs/tchcmp1.png', nil, 15, nil, nil, button_font)
|
||||||
|
|
||||||
|
dlg:add(Label(nil, nil, 'Set Controls', self.subtitle_font, Color(215, 0, 0), true))
|
||||||
|
|
||||||
|
box = HBox()
|
||||||
|
box.spacing = 30
|
||||||
|
-- text, font, x, y, callback, value, float, base_col, sel_color, press_col
|
||||||
|
box:add(TextInput('Step Forw.',
|
||||||
|
button_font,
|
||||||
|
nil, nil,
|
||||||
|
function(v) settings.forward = v end,
|
||||||
|
function() return settings.forward end))
|
||||||
|
box:add(TextInput('Step Back',
|
||||||
|
button_font,
|
||||||
|
nil, nil,
|
||||||
|
function(v) settings.backward = v end,
|
||||||
|
function() return settings.backward end))
|
||||||
|
|
||||||
|
dlg:add(box)
|
||||||
|
|
||||||
|
box = HBox()
|
||||||
|
box.spacing = 40
|
||||||
|
box:add(TextInput('Step Left',
|
||||||
|
button_font,
|
||||||
|
nil, nil,
|
||||||
|
function(v) settings.stepleft = v end,
|
||||||
|
function() return settings.stepleft end))
|
||||||
|
box:add(TextInput('Step Right',
|
||||||
|
button_font,
|
||||||
|
nil, nil,
|
||||||
|
function(v) settings.stepright = v end,
|
||||||
|
function() return settings.stepright end))
|
||||||
|
|
||||||
|
dlg:add(box)
|
||||||
|
|
||||||
|
box = HBox()
|
||||||
|
box.spacing = 42
|
||||||
|
box:add(TextInput('Turn Left',
|
||||||
|
button_font,
|
||||||
|
nil, nil,
|
||||||
|
function(v) settings.turnleft = v end,
|
||||||
|
function() return settings.turnleft end))
|
||||||
|
box:add(TextInput('Turn Right',
|
||||||
|
button_font,
|
||||||
|
nil, nil,
|
||||||
|
function(v) settings.turnright = v end,
|
||||||
|
function() return settings.turnright end))
|
||||||
|
|
||||||
|
dlg:add(box)
|
||||||
|
|
||||||
|
box = HBox()
|
||||||
|
|
||||||
|
box:add(TextButton(
|
||||||
|
'Set Controls',
|
||||||
|
button_font,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
function()
|
||||||
|
dlg:show()
|
||||||
|
end))
|
||||||
|
|
||||||
|
self.container:add(box)
|
||||||
|
|
||||||
|
-- Sound volume bar.
|
||||||
|
box = HBox()
|
||||||
|
|
||||||
|
box:add(Label(nil, nil, 'Sound Volume: ', button_font))
|
||||||
|
box:add(Bar(
|
||||||
|
function(v)
|
||||||
|
settings.soundvol = math.ceil(v)
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
return settings.soundvol
|
||||||
|
end,
|
||||||
|
0, 100,
|
||||||
|
170, 15))
|
||||||
|
|
||||||
|
self.container:add(box)
|
||||||
|
|
||||||
|
-- Music volume bar.
|
||||||
|
box = HBox()
|
||||||
|
box.spacing = 13
|
||||||
|
|
||||||
|
box:add(Label(nil, nil, 'Music Volume: ', button_font))
|
||||||
|
box:add(Bar(
|
||||||
|
function(v)
|
||||||
|
settings.musicvol = math.ceil(v)
|
||||||
|
sound_manager:update_volumes()
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
return settings.musicvol
|
||||||
|
end,
|
||||||
|
0, 100,
|
||||||
|
170, 15))
|
||||||
|
|
||||||
|
self.container:add(box)
|
||||||
|
|
||||||
|
-- Back button.
|
||||||
|
box = HBox()
|
||||||
|
box:add(TextButton(
|
||||||
|
'Go Back',
|
||||||
|
button_font,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
function()
|
||||||
|
settings:save_settings()
|
||||||
|
parent.next_menu = constants.MAIN_MENU
|
||||||
|
end))
|
||||||
|
self.container:add(box)
|
||||||
|
|
||||||
|
-- Register the dialog with the asset manager.
|
||||||
|
assets:register(self.name, dlg)
|
||||||
|
assets:register(self.name, self.subtitle_font)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return OptionsMenu
|
||||||
113
src/sound/sfx.lua
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Asset = require 'src.utils.asset'
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- SoundEffect is a simple wrapper around Löve's Source class to allow for
|
||||||
|
-- easy loading/unloading and automatically checking if a sound effect is valid
|
||||||
|
-- before using it.
|
||||||
|
local SoundEffect = make_class(Asset)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function SoundEffect:_init(file_name)
|
||||||
|
Asset._init(self, file_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:load()
|
||||||
|
if not self:is_loaded() then
|
||||||
|
self.sfx = love.audio.newSource(self.file_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:unload()
|
||||||
|
if self:isPlaying() then self:stop() end
|
||||||
|
self.sfx = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:is_loaded()
|
||||||
|
return self.sfx ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:setVolume(volume)
|
||||||
|
if self.sfx ~= nil then self.sfx:setVolume(volume) end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:setPitch(pitch)
|
||||||
|
if self.sfx ~= nil then self.sfx:setPitch(pitch) end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:setLooping(enable)
|
||||||
|
if self.sfx ~= nil then self.sfx:setLooping(enable) end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:getDuration()
|
||||||
|
if self.sfx ~= nil then
|
||||||
|
return self.sfx:getDuration()
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:isPlaying()
|
||||||
|
return self.sfx ~= nil and self.sfx:isPlaying()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:isPaused()
|
||||||
|
return self.sfx ~= nil and self.sfx:isPaused()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:isStopped()
|
||||||
|
return self.sfx ~= nil and self.sfx:isStopped()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:tell()
|
||||||
|
if self.sfx ~= nil then
|
||||||
|
return self.sfx:tell()
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:play()
|
||||||
|
if self.sfx ~= nil then self.sfx:play() end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:pause()
|
||||||
|
if self.sfx ~= nil then self.sfx:pause() end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundEffect:stop()
|
||||||
|
if self.sfx ~= nil then self.sfx:stop() end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return SoundEffect
|
||||||
57
src/sound/sndmngr.lua
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local settings = require 'src.utils.settings'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local SoundManager = make_class()
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function SoundManager:_init()
|
||||||
|
self.active_bgm = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundManager:play_sound(sfx)
|
||||||
|
local vol = math.max(math.min(settings.soundvol / 100, 1.0), 0.0)
|
||||||
|
sfx:setVolume(vol)
|
||||||
|
sfx:play()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundManager:play_music(bgm)
|
||||||
|
local vol = math.max(math.min(settings.musicvol / 100, 1.0), 0.0)
|
||||||
|
|
||||||
|
if self.active_bgm ~= nil then
|
||||||
|
self.active_bgm:stop()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.active_bgm = bgm
|
||||||
|
self.active_bgm:setVolume(vol)
|
||||||
|
self.active_bgm:play()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function SoundManager:update_volumes()
|
||||||
|
if self.active_bgm ~= nil then
|
||||||
|
local vol = math.max(math.min(settings.musicvol / 100, 1.0), 0.0)
|
||||||
|
self.active_bgm:setVolume(vol)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return SoundManager()
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local Intro = require 'src.gstates.intro'
|
local Intro = require 'src.gstates.intro'
|
||||||
|
local Menu = require 'src.gstates.menu'
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@@ -12,6 +13,7 @@ local Intro = require 'src.gstates.intro'
|
|||||||
-- Table of all valid game states.
|
-- Table of all valid game states.
|
||||||
local states = {
|
local states = {
|
||||||
Intro('intro', 1),
|
Intro('intro', 1),
|
||||||
|
Menu('menu', 2),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
121
src/ui/bar.lua
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local collisions = require 'src.utils.colls'
|
||||||
|
local UIElement = require 'src.ui.element'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Bar = make_class(UIElement)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Bar:_init(callback, val_fn, min, max, w, h, color, sel_color, press_col, float, x, y)
|
||||||
|
UIElement._init(self, x, y, float, false)
|
||||||
|
self.callback = callback
|
||||||
|
self.val_fn = val_fn
|
||||||
|
self.min = min
|
||||||
|
self.max = max
|
||||||
|
self.w = w
|
||||||
|
self.h = h
|
||||||
|
self.base_col = color ~= nil and color or Color(255, 255, 255)
|
||||||
|
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
|
||||||
|
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
|
||||||
|
self.disbl_col = Color(95, 63, 75)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bar:set_dimensions()
|
||||||
|
self.w = self.w
|
||||||
|
self.h = self.h
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bar:draw()
|
||||||
|
local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
|
||||||
|
|
||||||
|
-- Convert the variable's value to the [0, 1] space.
|
||||||
|
local v = (self.val_fn() + math.abs(self.min)) / (self.max + math.abs(self.min))
|
||||||
|
|
||||||
|
love.graphics.setColor(color.r, color.g, color.b)
|
||||||
|
|
||||||
|
-- Render the bar's outline.
|
||||||
|
love.graphics.rectangle('line', self.x, self.y, self.w, self.h)
|
||||||
|
|
||||||
|
-- Render the bar's content using the [0, 1] value as a proportion of the bar's width.
|
||||||
|
love.graphics.rectangle('fill', self.x, self.y, self.w * v, self.h)
|
||||||
|
love.graphics.setColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bar:_mouse2bar(x)
|
||||||
|
-- Take the x coord to the [0, 1] space, with clamping.
|
||||||
|
local v = math.max(math.min(((x - self.x) / self.w), 1.0), 0.0)
|
||||||
|
|
||||||
|
-- Convert the value to a horizontal bar coordinate and return it.
|
||||||
|
return (v * (self.max + math.abs(self.min))) - self.min
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bar:mousemoved(x, y)
|
||||||
|
-- Select if the pointer is inside the button's bounding rect.
|
||||||
|
self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
|
||||||
|
-- If the button was pressed then check if the pointer is no longer inside the button.
|
||||||
|
if self.pressed then
|
||||||
|
-- If it's not, then mark the button as "was pressed".
|
||||||
|
self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
self.was_pressed = true
|
||||||
|
self.callback(self:_mouse2bar(x))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If the button was pressed and the pointer is inside the button right now.
|
||||||
|
if self.was_pressed and collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) then
|
||||||
|
-- Then mark the button as pressed again.
|
||||||
|
self.pressed = true
|
||||||
|
self.was_pressed = false
|
||||||
|
self.callback(self:_mouse2bar(x))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bar:mousepressed(x, y, btn)
|
||||||
|
-- If the pointer was inside the button when it was pressed then mark the button as pressed.
|
||||||
|
if btn == 0 then
|
||||||
|
self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Bar:mousereleased(x, _, btn)
|
||||||
|
if btn == 0 then
|
||||||
|
if self.pressed then
|
||||||
|
-- If the button was pressed then execute the callback if any and unmark as pressed.
|
||||||
|
if self.callback ~= nil then
|
||||||
|
self.callback(self:_mouse2bar(x))
|
||||||
|
end
|
||||||
|
|
||||||
|
self.pressed = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The button no longer was pressed.
|
||||||
|
self.was_pressed = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Bar
|
||||||
90
src/ui/button.lua
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local collisions = require 'src.utils.colls'
|
||||||
|
local UIElement = require 'src.ui.element'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Button: UIElement
|
||||||
|
local Button = make_class(UIElement)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param x number
|
||||||
|
---@param y number
|
||||||
|
---@param callback function
|
||||||
|
---@param float boolean
|
||||||
|
function Button:_init(x, y, callback, float)
|
||||||
|
UIElement._init(self, x, y, float, false)
|
||||||
|
self.selected = false
|
||||||
|
self.pressed = false
|
||||||
|
self.was_pressed = false
|
||||||
|
self.callback = callback
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Button:set_dimensions()
|
||||||
|
self.w = 0
|
||||||
|
self.h = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Button:mousemoved(x, y)
|
||||||
|
-- Select if the pointer is inside the button's bounding rect.
|
||||||
|
self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
|
||||||
|
-- If the button was pressed then check if the pointer is no longer inside the button.
|
||||||
|
if self.pressed then
|
||||||
|
-- If it's not, then mark the button as "was pressed".
|
||||||
|
self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
self.was_pressed = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If the button was pressed and the pointer is inside the button right now.
|
||||||
|
if self.was_pressed and collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) then
|
||||||
|
-- Then mark the button as pressed again.
|
||||||
|
self.pressed = true
|
||||||
|
self.was_pressed = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Button:mousepressed(x, y, btn)
|
||||||
|
-- If the pointer was inside the button when it was pressed then mark the button as pressed.
|
||||||
|
if btn == 0 then
|
||||||
|
self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Button:mousereleased(_, _, btn)
|
||||||
|
if btn == 0 then
|
||||||
|
if self.pressed then
|
||||||
|
-- If the button was pressed then execute the callback if any and unmark as pressed.
|
||||||
|
if self.callback ~= nil then
|
||||||
|
self.callback()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.pressed = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The button no longer was pressed.
|
||||||
|
self.was_pressed = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Button
|
||||||
55
src/ui/chkbox.lua
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Button = require 'src.ui.button'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Checkbox = make_class(Button)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Checkbox:_init(callback, value, w, h, color, sel_color, press_col, float, x, y)
|
||||||
|
Button._init(self, x, y, callback, float)
|
||||||
|
self.value = value
|
||||||
|
self.w = w ~= nil and w or 20
|
||||||
|
self.h = h ~= nil and h or 20
|
||||||
|
self.base_col = color ~= nil and color or Color(255, 255, 255)
|
||||||
|
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
|
||||||
|
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
|
||||||
|
self.disbl_col = Color(95, 63, 75)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Checkbox:set_dimensions()
|
||||||
|
self.w = self.w
|
||||||
|
self.h = self.h
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Checkbox:draw()
|
||||||
|
local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
|
||||||
|
local mode = nil
|
||||||
|
if self.value() then mode = 'fill' else mode = 'line' end
|
||||||
|
|
||||||
|
love.graphics.setColor(color.r, color.g, color.b)
|
||||||
|
love.graphics.rectangle(mode, self.x, self.y, self.w, self.h)
|
||||||
|
love.graphics.setColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Checkbox
|
||||||
35
src/ui/cursor.lua
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Sprite = require 'src.graphics.sprite'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Cursor = make_class(Sprite)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Cursor:_init(x, y)
|
||||||
|
Sprite._init(self, 'imgs/pointer.png', x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Cursor:mousemoved(x, y)
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Cursor
|
||||||
117
src/ui/dialog.lua
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local dialog_manager = require 'src.ui.dlgmngr'
|
||||||
|
local VBox = require 'src.ui.vbox'
|
||||||
|
local Sprite = require 'src.graphics.sprite'
|
||||||
|
local TextButton = require 'src.ui.textbtn'
|
||||||
|
local HBox = require 'src.ui.hbox'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local Dialog = make_class(VBox)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Dialog:_init(bckg, spacing, padding, close_btn, accept_btn, font)
|
||||||
|
VBox._init(self, nil, nil, nil, nil, spacing, false)
|
||||||
|
self.spacing = spacing ~= nil and spacing or 10
|
||||||
|
self.padding = padding ~= nil and padding or 15
|
||||||
|
self.background = Sprite(bckg)
|
||||||
|
self.shown = false
|
||||||
|
|
||||||
|
local close = nil
|
||||||
|
|
||||||
|
if close_btn ~= nil then
|
||||||
|
close = close_btn
|
||||||
|
else
|
||||||
|
close = TextButton(
|
||||||
|
'Close',
|
||||||
|
font,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
function()
|
||||||
|
self:hide()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local accept = nil
|
||||||
|
if accept_btn ~= nil then accept = accept_btn end
|
||||||
|
|
||||||
|
-- Create a container for the close and accept button and add them.
|
||||||
|
local box = HBox(nil, nil, nil, nil, 10, true)
|
||||||
|
box:add(close)
|
||||||
|
|
||||||
|
if accept ~= nil then box:add(accept) end
|
||||||
|
|
||||||
|
self.elements[9001] = box
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Dialog:add(element)
|
||||||
|
table.insert(self.elements, element)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Dialog:load()
|
||||||
|
self.background:load()
|
||||||
|
self:set_dimensions()
|
||||||
|
VBox.load(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Dialog:set_dimensions()
|
||||||
|
self.w = self.background.sprite:getWidth()
|
||||||
|
self.h = self.background.sprite:getHeight()
|
||||||
|
|
||||||
|
-- Center the dialog on the screen.
|
||||||
|
self.x = (320 - self.w) / 2
|
||||||
|
self.y = (200 - self.h) / 2
|
||||||
|
|
||||||
|
self.background.x = self.x
|
||||||
|
self.background.y = self.y
|
||||||
|
|
||||||
|
-- Add padding.
|
||||||
|
self.x = self.x + self.padding
|
||||||
|
self.y = self.y + self.padding / 2
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Dialog:draw()
|
||||||
|
love.graphics.setColor(0, 0, 0)
|
||||||
|
love.graphics.rectangle('line', self.x - self.padding - 1, self.y - (self.padding / 2) - 1, self.w + 2, self.h + 2)
|
||||||
|
love.graphics.setColor()
|
||||||
|
|
||||||
|
self.background:draw()
|
||||||
|
VBox.draw(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Dialog:show()
|
||||||
|
if not self.shown then
|
||||||
|
dialog_manager:add(self)
|
||||||
|
self.shown = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Dialog:hide()
|
||||||
|
dialog_manager:remove(self)
|
||||||
|
self.shown = false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Dialog
|
||||||
104
src/ui/dlgmngr.lua
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Drawable = require 'src.graphics.drawable'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local DialogManager = make_class(Drawable)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function DialogManager:_init()
|
||||||
|
Drawable._init(self)
|
||||||
|
self.dialogs = {}
|
||||||
|
self.count = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:add(dialog)
|
||||||
|
self.dialogs[dialog] = true
|
||||||
|
self.count = self.count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:remove(dialog)
|
||||||
|
self.dialogs[dialog] = nil
|
||||||
|
self.count = math.max(self.count - 1, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:empty()
|
||||||
|
return self.count == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:update(dt)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:update(dt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:draw()
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:keypressed(key, code, isrepeat)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:keypressed(key, code, isrepeat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:textinput(text)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:textinput(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:keyreleased(key, code)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:keyreleased(key, code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:mousemoved(x, y, dx, dy)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:mousemoved(x, y, dx, dy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:mousepressed(x, y, btn)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:mousepressed(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function DialogManager:mousereleased(x, y, btn)
|
||||||
|
for d, _ in pairs(self.dialogs) do
|
||||||
|
d:mousereleased(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return DialogManager()
|
||||||
84
src/ui/element.lua
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Asset = require 'src.utils.asset'
|
||||||
|
local Drawable = require 'src.graphics.drawable'
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local focused_element = nil
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class UIElement: Drawable, Asset
|
||||||
|
local UIElement = make_class(Drawable, Asset)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param x integer
|
||||||
|
---@param y integer
|
||||||
|
---@param float boolean
|
||||||
|
---@param focusable boolean
|
||||||
|
function UIElement:_init(x, y, float, focusable)
|
||||||
|
Asset._init(self)
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.w = nil
|
||||||
|
self.h = nil
|
||||||
|
self.float_right = float and float or false
|
||||||
|
self.focusable = focusable ~= nil and focusable or false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:set_dimensions()
|
||||||
|
self.w = 0
|
||||||
|
self.h = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:load()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:unload()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:is_loaded()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:focus()
|
||||||
|
if self.focusable then
|
||||||
|
focused_element = self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:blur()
|
||||||
|
if self.focusable and focused_element == self then
|
||||||
|
focused_element = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function UIElement:is_focused()
|
||||||
|
return self.focusable and focused_element == self
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return UIElement
|
||||||
73
src/ui/font.lua
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Asset = require 'src.utils.asset'
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Font: Asset
|
||||||
|
-- Font is a simple wrapper around Löve's own Font class to allow for
|
||||||
|
-- easy loading/unloading and automatically checking if it's is valid
|
||||||
|
-- before using it.
|
||||||
|
local Font = make_class(Asset)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param file_name string
|
||||||
|
---@param size number
|
||||||
|
function Font:_init(file_name, size)
|
||||||
|
self.file_name = string.format('assets/%s', file_name)
|
||||||
|
self.size = (size ~= nil and size) or 20
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:load()
|
||||||
|
if not self:is_loaded() then
|
||||||
|
self.f = love.graphics.newFont(self.file_name, self.size)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:unload()
|
||||||
|
self.f = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:is_loaded()
|
||||||
|
return self.f ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:set()
|
||||||
|
if self.f ~= nil then love.graphics.setFont(self.f) end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:unset()
|
||||||
|
love.graphics.setFont()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:get_width(text)
|
||||||
|
if self.f ~= nil then return self.f:getWidth(text) else return nil end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Font:get_height(text)
|
||||||
|
if self.f ~= nil then return self.f:getHeight(text) else return nil end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Font
|
||||||
63
src/ui/hbox.lua
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Layout = require 'src.ui.layout'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class HBox: Layout
|
||||||
|
local HBox = make_class(Layout)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function HBox:_init(x, y, w, h, spacing, float)
|
||||||
|
Layout._init(self, x, y, w, h, spacing, float)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function HBox:load()
|
||||||
|
Layout.load(self)
|
||||||
|
|
||||||
|
local _x = self.x
|
||||||
|
|
||||||
|
-- Load required assets if needed and then compute the coordinates of each button.
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v.y = self.y
|
||||||
|
|
||||||
|
v.x = _x
|
||||||
|
_x = _x + v.w + self.spacing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function HBox:set_dimensions()
|
||||||
|
if self.w == nil then
|
||||||
|
self.w = 0
|
||||||
|
for i, v in pairs(self.elements) do
|
||||||
|
self.w = self.w + v.w
|
||||||
|
if i < #self.elements then self.w = self.w + self.spacing end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.h == nil then
|
||||||
|
self.h = 0
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
if v.h > self.h then self.h = v.h end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return HBox
|
||||||
74
src/ui/label.lua
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local UIElement = require 'src.ui.element'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Label: UIElement
|
||||||
|
local Label = make_class(UIElement)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param x number
|
||||||
|
---@param y number
|
||||||
|
---@param text string
|
||||||
|
---@param font Font
|
||||||
|
---@param color Color
|
||||||
|
---@param float boolean
|
||||||
|
function Label:_init(x, y, text, font, color, float)
|
||||||
|
UIElement._init(self, x, y, float, false)
|
||||||
|
self.text = text
|
||||||
|
self.font = font
|
||||||
|
self.color = color ~= nil and color or Color(255, 255, 255)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Label:set_dimensions()
|
||||||
|
self.w = self.font:get_width(self.text)
|
||||||
|
self.h = self.font:get_height(self.text)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Label:load()
|
||||||
|
self.font:load()
|
||||||
|
|
||||||
|
-- If the label's size has not been computed then do it.
|
||||||
|
if self.w == nil or self.h == nil then self:set_dimensions() end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Label:unload()
|
||||||
|
self.font:unload()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Label:is_loaded()
|
||||||
|
return self.font:is_loaded() and self.w ~= nil and self.h ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Label:draw()
|
||||||
|
love.graphics.setColor(self.color.r, self.color.g, self.color.b)
|
||||||
|
self.font:set()
|
||||||
|
love.graphics.print(self.text, self.x, self.y)
|
||||||
|
self.font:unset()
|
||||||
|
love.graphics.setColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Label
|
||||||
118
src/ui/layout.lua
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local UIElement = require 'src.ui.element'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Layout: UIElement
|
||||||
|
local Layout = make_class(UIElement)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Layout:_init(x, y, w, h, spacing, float)
|
||||||
|
UIElement._init(self, x, y, float, false)
|
||||||
|
self.x = x ~= nil and x or 0
|
||||||
|
self.y = y ~= nil and y or 0
|
||||||
|
self.w = w
|
||||||
|
self.h = h
|
||||||
|
self.spacing = spacing ~= nil and spacing or 10
|
||||||
|
self.elements = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:add(element)
|
||||||
|
table.insert(self.elements, element)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:load()
|
||||||
|
-- Load required assets if needed and then compute the coordinates of each button.
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
if v.is_a[UIElement] then
|
||||||
|
v:load()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self:set_dimensions()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:unload()
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
if v.is_a[UIElement] then
|
||||||
|
v:unload()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:update(dt)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:update(dt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:draw()
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:draw()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:keypressed(key, code, isrepeat)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:keypressed(key, code, isrepeat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:textinput(text)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:textinput(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:keyreleased(key, code)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:keyreleased(key, code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:mousemoved(x, y, dx, dy)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:mousemoved(x, y, dx, dy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:mousepressed(x, y, btn)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:mousepressed(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Layout:mousereleased(x, y, btn)
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
v:mousereleased(x, y, btn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Layout
|
||||||
74
src/ui/textbtn.lua
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Button = require 'src.ui.button'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local TextButton = make_class(Button)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TextButton:_init(text, font, x, y, callback, float, base_col, sel_color, press_col)
|
||||||
|
Button._init(self, x, y, callback, float)
|
||||||
|
self.font = font
|
||||||
|
self.text = text
|
||||||
|
self.base_col = base_col ~= nil and base_col or Color(255, 255, 255)
|
||||||
|
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
|
||||||
|
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
|
||||||
|
self.disbl_col = Color(95, 63, 75)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextButton:load()
|
||||||
|
if not self.font:is_loaded() then
|
||||||
|
self.font:load()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If the label's size has not been computed then do it.
|
||||||
|
if self.w == nil or self.h == nil then self:set_dimensions() end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextButton:unload()
|
||||||
|
self.font:unload()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextButton:is_loaded()
|
||||||
|
return self.font:is_loaded() and self.w ~= nil and self.h ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextButton:set_dimensions()
|
||||||
|
self.w = self.font:get_width(self.text)
|
||||||
|
self.h = self.font:get_height(self.text)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextButton:draw()
|
||||||
|
local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
|
||||||
|
|
||||||
|
love.graphics.setColor(color.r, color.g, color.b)
|
||||||
|
self.font:set()
|
||||||
|
love.graphics.print(self.text, self.x, self.y)
|
||||||
|
self.font:unset()
|
||||||
|
love.graphics.setColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return TextButton
|
||||||
118
src/ui/textinpt.lua
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local collisions = require 'src.utils.colls'
|
||||||
|
local UIElement = require 'src.ui.element'
|
||||||
|
local Color = require 'src.utils.color'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class CharInput: UIElement
|
||||||
|
local TextInput = make_class(UIElement)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param text string
|
||||||
|
---@param font Font
|
||||||
|
---@param x number
|
||||||
|
---@param y number
|
||||||
|
---@param callback function
|
||||||
|
---@param value function
|
||||||
|
---@param float boolean
|
||||||
|
---@param base_col Color
|
||||||
|
---@param sel_color Color
|
||||||
|
---@param press_col Color
|
||||||
|
function TextInput:_init(text, font, x, y, callback, value, float, base_col, sel_color, press_col)
|
||||||
|
UIElement._init(self, x, y, float, true)
|
||||||
|
self.callback = callback
|
||||||
|
self.value = value
|
||||||
|
self.font = font
|
||||||
|
self.text = text
|
||||||
|
self.base_col = base_col ~= nil and base_col or Color(255, 255, 255)
|
||||||
|
self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0)
|
||||||
|
self.press_col = press_col ~= nil and press_col or Color(99, 99, 139)
|
||||||
|
self.disbl_col = Color(95, 63, 75)
|
||||||
|
self.selected = false
|
||||||
|
self.pressed = false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:load()
|
||||||
|
self.font:load()
|
||||||
|
|
||||||
|
-- If the label's size has not been computed then do it.
|
||||||
|
if self.w == nil or self.h == nil then self:set_dimensions() end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:unload()
|
||||||
|
self.font:unload()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:is_loaded()
|
||||||
|
return self.font:is_loaded() and self.w ~= nil and self.h ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:set_dimensions()
|
||||||
|
self.w = self.font:get_width(self.text .. 'm')
|
||||||
|
self.h = self.font:get_height(self.text)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:draw()
|
||||||
|
local color = self.callback == nil and self.disbl_col or (((self.pressed or self:is_focused()) and self.press_col) or ((self.selected and self.sel_color) or self.base_col))
|
||||||
|
|
||||||
|
love.graphics.setColor(color.r, color.g, color.b)
|
||||||
|
self.font:set()
|
||||||
|
|
||||||
|
if self:is_focused() then
|
||||||
|
love.graphics.print(self.text .. ': ?', self.x, self.y)
|
||||||
|
else
|
||||||
|
love.graphics.print(self.text .. ': ' .. self.value(), self.x, self.y)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.font:unset()
|
||||||
|
love.graphics.setColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:mousemoved(x, y)
|
||||||
|
-- Select if the pointer is inside the button's bounding rect.
|
||||||
|
self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:mousepressed(_, _, btn)
|
||||||
|
-- If the pointer was inside the button when it was pressed then mark the button as pressed.
|
||||||
|
if btn == 0 and self.selected then
|
||||||
|
self:focus()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function TextInput:keypressed(key)
|
||||||
|
if self:is_focused() then
|
||||||
|
if #key == 1 then
|
||||||
|
if self.callback ~= nil then self.callback(key) end
|
||||||
|
self:blur()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return TextInput
|
||||||
66
src/ui/vbox.lua
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Layout = require 'src.ui.layout'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class VBox: Layout
|
||||||
|
local VBox = make_class(Layout)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function VBox:_init(x, y, w, h, spacing, float)
|
||||||
|
Layout._init(self, x, y, w, h, spacing, float)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function VBox:load()
|
||||||
|
Layout.load(self)
|
||||||
|
|
||||||
|
local _y = self.y
|
||||||
|
|
||||||
|
-- Load required assets if needed and then compute the coordinates of each button.
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
if v.float_right then
|
||||||
|
v.x = self.w - v.w
|
||||||
|
else
|
||||||
|
v.x = self.x
|
||||||
|
end
|
||||||
|
|
||||||
|
v.y = _y
|
||||||
|
_y = _y + v.h + self.spacing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function VBox:set_dimensions()
|
||||||
|
if self.w == nil then
|
||||||
|
self.w = 0
|
||||||
|
for _, v in pairs(self.elements) do
|
||||||
|
if v.w > self.w then self.w = v.w end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.h == nil then
|
||||||
|
self.h = 0
|
||||||
|
for i, v in pairs(self.elements) do
|
||||||
|
self.h = self.h + v.h
|
||||||
|
if i < #self.elements then self.h = self.h + self.spacing end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return VBox
|
||||||
44
src/utils/asset.lua
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Asset
|
||||||
|
local Asset = make_class()
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Asset:_init(file_name)
|
||||||
|
self.file_name = string.format('assets/%s', file_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Asset:load()
|
||||||
|
error 'Attempted to load unimplemented asset.'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Asset:unload()
|
||||||
|
error 'Attempted to unload unimplemented asset.'
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Asset:is_loaded()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Asset
|
||||||
135
src/utils/asstmngr.lua
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
local Drawable = require 'src.graphics.drawable'
|
||||||
|
local Asset = require 'src.utils.asset'
|
||||||
|
local Sprite = require 'src.graphics.sprite'
|
||||||
|
local Font = require 'src.ui.font'
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local AssetManager = make_class(Drawable)
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Helper functions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local function _load(manager, owner)
|
||||||
|
if manager.assets[owner] ~= nil then
|
||||||
|
for k, _ in pairs(manager.assets[owner]) do
|
||||||
|
if k.is_a ~= nil and k.is_a[Asset] then
|
||||||
|
k:load()
|
||||||
|
end
|
||||||
|
coroutine.yield(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function AssetManager:_init()
|
||||||
|
Drawable._init(self)
|
||||||
|
self.assets = {}
|
||||||
|
self.bckg = Sprite('imgs/floppy.png')
|
||||||
|
self.font = Font('fonts/BBrick.ttf', 40)
|
||||||
|
self.co = nil
|
||||||
|
|
||||||
|
self.bckg:load()
|
||||||
|
self.font:load()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function AssetManager:unload(owner)
|
||||||
|
-- If the owner is known...
|
||||||
|
if self.assets[owner] ~= nil then
|
||||||
|
-- Iterate over it's asset set and unload everything.
|
||||||
|
for k, _ in pairs(self.assets[owner]) do
|
||||||
|
if k.is_a ~= nil and k.is_a[Asset] then
|
||||||
|
k:unload()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function AssetManager:update(owner)
|
||||||
|
if self.assets[owner] ~= nil then
|
||||||
|
if self.assets[owner].co == nil then
|
||||||
|
self.assets[owner].co = coroutine.create(_load)
|
||||||
|
end
|
||||||
|
|
||||||
|
local errorfree, retval = coroutine.resume(self.assets[owner].co, self, owner)
|
||||||
|
|
||||||
|
if errorfree then
|
||||||
|
self.assets[owner].done = retval
|
||||||
|
|
||||||
|
if retval then
|
||||||
|
self.assets[owner].co = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
error(retval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function AssetManager:draw()
|
||||||
|
self.bckg:draw()
|
||||||
|
|
||||||
|
love.graphics.setColor(195, 147, 123)
|
||||||
|
self.font:set()
|
||||||
|
love.graphics.print('Loading...', 5, 150)
|
||||||
|
self.font:unset()
|
||||||
|
love.graphics.setColor()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function AssetManager:register(owner, asset)
|
||||||
|
-- If the owner is new, then create an asset set for it.
|
||||||
|
if self.assets[owner] == nil then
|
||||||
|
self.assets[owner] = {
|
||||||
|
done = false,
|
||||||
|
co = nil,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Store the asset in the set.
|
||||||
|
self.assets[owner][asset] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function AssetManager:remove(owner, asset)
|
||||||
|
-- If the owner is new, then create an asset set for it.
|
||||||
|
if self.assets[owner] ~= nil then
|
||||||
|
-- Unload the asset just in case.
|
||||||
|
if self.assets[owner][asset] ~= nil then
|
||||||
|
self.assets[owner][asset]:unload()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Then remove it from the set.
|
||||||
|
self.assets[owner][asset] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function AssetManager:done(owner)
|
||||||
|
return self.assets[owner] ~= nil and self.assets[owner].done
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return AssetManager()
|
||||||
@@ -2,15 +2,16 @@
|
|||||||
-- Methods
|
-- Methods
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Single inheritance version of the sample code from
|
--- Code from http://lua-users.org/wiki/ObjectOrientationTutorial
|
||||||
-- http://lua-users.org/wiki/ObjectOrientationTutorial
|
---@param ... table Optional base classes
|
||||||
local function make_class(BaseClass)
|
---@return table cls A class definition
|
||||||
|
local function make_class(...)
|
||||||
-- "cls" is the new class
|
-- "cls" is the new class
|
||||||
local cls = {}
|
local cls, bases = {}, {...}
|
||||||
|
|
||||||
-- copy base class contents into the new class
|
-- copy base class contents into the new class
|
||||||
if BaseClass ~= nil then
|
for _, base in ipairs(bases) do
|
||||||
for k, v in pairs(BaseClass) do
|
for k, v in pairs(base) do
|
||||||
cls[k] = v
|
cls[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -19,8 +20,11 @@ local function make_class(BaseClass)
|
|||||||
-- so you can do an "instance of" check using my_instance.is_a[MyClass]
|
-- so you can do an "instance of" check using my_instance.is_a[MyClass]
|
||||||
cls.__index, cls.is_a = cls, {[cls] = true}
|
cls.__index, cls.is_a = cls, {[cls] = true}
|
||||||
|
|
||||||
if BaseClass ~= nil then
|
for _, base in ipairs(bases) do
|
||||||
cls.is_a[BaseClass] = true
|
for c in pairs(base.is_a) do
|
||||||
|
cls.is_a[c] = true
|
||||||
|
end
|
||||||
|
cls.is_a[base] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- the class's __call metamethod
|
-- the class's __call metamethod
|
||||||
|
|||||||
17
src/utils/colls.lua
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local collisions = {
|
||||||
|
-- Default setting values.
|
||||||
|
point_in_square = function(x, y, ox, oy, w, h)
|
||||||
|
return x >= ox and x <= ox + w and y >= oy and y <= oy + h
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return collisions
|
||||||
31
src/utils/color.lua
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Color
|
||||||
|
local Color = make_class()
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Class methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Color:_init(r, g, b)
|
||||||
|
self.r = r ~= nil and r or 255
|
||||||
|
self.g = g ~= nil and g or 255
|
||||||
|
self.b = b ~= nil and b or 255
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Color
|
||||||
34
src/utils/mgclines.lua
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- From https://stackoverflow.com/a/19327160
|
||||||
|
-- Cargo cult programming ahoy!!
|
||||||
|
local function magiclines( str )
|
||||||
|
local pos
|
||||||
|
pos = 1
|
||||||
|
|
||||||
|
return function()
|
||||||
|
if not pos then return nil end
|
||||||
|
|
||||||
|
local p1, p2 = string.find( str, "\r?\n", pos )
|
||||||
|
local line
|
||||||
|
|
||||||
|
if p1 then
|
||||||
|
line = str:sub( pos, p1 - 1 )
|
||||||
|
pos = p2 + 1
|
||||||
|
else
|
||||||
|
line = str:sub( pos )
|
||||||
|
pos = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return magiclines
|
||||||
136
src/utils/settings.lua
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Imports
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local love = require 'love'
|
||||||
|
local magiclines = require 'src.utils.mgclines'
|
||||||
|
local make_class = require 'src.utils.classes'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Constants
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local SETTINGS_PATH = 'settings.ini'
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module definitions
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@class Settings
|
||||||
|
local Settings = make_class()
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Private module methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Settings:_init()
|
||||||
|
-- Default setting values.
|
||||||
|
self.permadeath = true
|
||||||
|
self.forward = 'w'
|
||||||
|
self.backward = 's'
|
||||||
|
self.stepleft = 'a'
|
||||||
|
self.stepright = 'd'
|
||||||
|
self.turnleft = 'q'
|
||||||
|
self.turnright = 'e'
|
||||||
|
self.musicvol = 75
|
||||||
|
self.soundvol = 100
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Settings:_parse_settings_str(s)
|
||||||
|
-- For each line in the data string.
|
||||||
|
for line in magiclines(s) do
|
||||||
|
-- Check if the line matches a key=value pair
|
||||||
|
local k, v = string.match(line, '(%w+)=(.+)')
|
||||||
|
|
||||||
|
if k and v then
|
||||||
|
-- If the line matches then check if it has a known settings key.
|
||||||
|
if self[k] ~= nil then
|
||||||
|
-- If the key is valid then cast the value to it's expected data type and store it.
|
||||||
|
-- Fail if the cast is not doable.
|
||||||
|
if v == 'true' then
|
||||||
|
if type(self[k]) ~= 'boolean' then error(string.format('Invalid value for %s in settings', k)) end
|
||||||
|
self[k] = true
|
||||||
|
elseif v == 'false' then
|
||||||
|
if type(self[k]) ~= 'boolean' then error(string.format('Invalid value for %s in settings', k)) end
|
||||||
|
self[k] = false
|
||||||
|
elseif tonumber(v) then
|
||||||
|
if type(self[k]) ~= 'number' then error(string.format('Invalid value for %s in settings', k)) end
|
||||||
|
self[k] = tonumber(v)
|
||||||
|
else
|
||||||
|
self[k] = v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Fail on an unknown key.
|
||||||
|
error(string.format('Unknown settings key "%s"', k))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Settings:_get_settings_str()
|
||||||
|
-- Start with the settings category.
|
||||||
|
local s = '[settings]\n'
|
||||||
|
|
||||||
|
-- For each value in the settings table.
|
||||||
|
for k, v in pairs(self) do
|
||||||
|
-- If the value isn't a function then it is a setting.
|
||||||
|
if type(v) ~= 'function' then
|
||||||
|
-- Format the value as key=value.
|
||||||
|
s = s .. string.format('%s=%s\n', k, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Settings:_open_or_create()
|
||||||
|
if not love.filesystem.exists(SETTINGS_PATH) then
|
||||||
|
-- If the settings file doesn't exist then create it with the default values.
|
||||||
|
local setts = self:_get_settings_str()
|
||||||
|
love.filesystem.write(SETTINGS_PATH, setts)
|
||||||
|
return setts
|
||||||
|
else
|
||||||
|
if not love.filesystem.isFile(SETTINGS_PATH) then
|
||||||
|
-- Fail if the settings path points to a directory.
|
||||||
|
error ("Settings path exists and isn't a file")
|
||||||
|
else
|
||||||
|
-- Else read the settings.
|
||||||
|
return love.filesystem.read(SETTINGS_PATH)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Public module methods
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function Settings:load_settings()
|
||||||
|
-- Obtain the settings data and parse it.
|
||||||
|
local s = self:_open_or_create()
|
||||||
|
self:_parse_settings_str(s)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Settings:save_settings()
|
||||||
|
if not love.filesystem.exists(SETTINGS_PATH) or love.filesystem.isFile(SETTINGS_PATH) then
|
||||||
|
-- If the settings file doesn't exist or it exists and is a file then save the current data.
|
||||||
|
love.filesystem.write(SETTINGS_PATH, self:_get_settings_str())
|
||||||
|
else
|
||||||
|
-- Fail if the settings path points to a directory.
|
||||||
|
error("Settings path exists and isn't a file")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
-- Module return
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return Settings()
|
||||||